-
-
Notifications
You must be signed in to change notification settings - Fork 195
[Flynn] Week6 #464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
[Flynn] Week6 #464
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
96f433c
Solution: Valid Parentheses
obzva eefe910
Solution: Container with Most Water
obzva b0a4234
Fix: line lint
obzva 02e60bb
Solution: Design Add and Search Words Data Structure
obzva 159b87f
Solution: Longest Increasing Subsequence
obzva 7ba9cdd
Comment: Longest Increasing Subsequence
obzva 853a332
Solution: Spiral Matrix
obzva 44ac5da
Refactor: Design Add and Search Words Data Structure
obzva File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* 풀이 | ||
* - container의 밑변이 넓고 높이가 높을 수록 저장하는 물의 양이 많습니다 | ||
* - 따라서 밑변이 가장 넓은 container부터 탐색하면 탐색 효율을 높일 수 있다는 생각을 했습니다 | ||
* - 양 끝에서부 two pointer를 이용하여 탐색을 시작합니다 | ||
* - lo, hi 중에서 높이가 더 낮은 pointer를 안쪽으로 이동시킵니다 | ||
* - 왜냐하면 높이가 더 낮은 pointer를 이동시켰을 때 기존 container보다 더 높이가 높은 container를 만들 수 있는 가능성이 생기기 때문입니다 | ||
* | ||
* Big O | ||
* - N: 주어진 배열 height의 크기 | ||
* | ||
* - Time complexity: O(N) | ||
* - 배열 height를 조회하므로 전체 실행시간 또한 N에 비례하여 선형적으로 증가합니다 | ||
* | ||
* - Space complexity: O(1) | ||
*/ | ||
|
||
class Solution { | ||
public: | ||
int maxArea(vector<int>& height) { | ||
int n = height.size(); | ||
int lo = 0; | ||
int hi = n - 1; | ||
|
||
int res = 0; | ||
while (lo < hi) { | ||
int w = hi - lo; | ||
int h = min(height[lo], height[hi]); | ||
|
||
res = max(res, w * h); | ||
|
||
if (height[lo] > height[hi]) { | ||
--hi; | ||
} else { | ||
++lo; | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** | ||
* 풀이 | ||
* - Trie 구조를 활용하여 풀이할 수 있습니다 | ||
* - wildcard인 '.'에 대한 처리가 필요합니다 | ||
* | ||
* Big O | ||
* - N: 주어지는 문자열 word의 길이 | ||
* - M: 현재 WordDictionary에 저장되어 있는 TrieNode의 수 | ||
* | ||
* - void addWord(string word) | ||
* - Time complexity: O(N) | ||
* - Space complexity: O(N) | ||
* - 최악의 경우 word의 모든 문자에 대해 새로운 TrieNode를 추가해야 합니다 | ||
* | ||
* - bool search(string word) | ||
* - bool _search(string word, int idx, TrieNode* node) | ||
* - Time complexity: best O(N), worst O(M) < O(26^N) | ||
* - wildcard 사용 및 기존에 저장된 word의 상태에 따라 달라집니다 | ||
* - Space complexity: O(N) | ||
* - _search가 재귀적으로 호출되므로 재귀 호출 스택의 깊이만큼 추가적인 공간이 사용됩니다 | ||
* - 재귀 호출 스택의 깊이는 현재 찾는 word의 길이에 선형적으로 비례합니다 | ||
*/ | ||
|
||
class TrieNode { | ||
public: | ||
array<TrieNode*, 27> links; | ||
bool word; | ||
|
||
TrieNode(): word(false) { | ||
links.fill(nullptr); | ||
} | ||
}; | ||
|
||
class WordDictionary { | ||
public: | ||
WordDictionary(): root(new TrieNode()) {} | ||
|
||
void addWord(string word) { | ||
TrieNode* current = root; | ||
|
||
for (char c : word) { | ||
if (current->links[c - 'a'] == nullptr) { | ||
current->links[c - 'a'] = new TrieNode(); | ||
} | ||
current = current->links[c - 'a']; | ||
} | ||
|
||
current->word = true; | ||
} | ||
|
||
bool search(string word) { | ||
return _search(word, 0, root); | ||
} | ||
|
||
private: | ||
TrieNode* root; | ||
|
||
bool _search(string word, int idx, TrieNode* node) { | ||
if (node == nullptr) return false; | ||
|
||
if (word.size() == idx) return node->word; | ||
|
||
char c = word[idx]; | ||
|
||
if (c != '.') { | ||
TrieNode* next_node = node->links[c - 'a']; | ||
int next_idx = idx + 1; | ||
|
||
return _search(word, next_idx, next_node); | ||
} else { | ||
for (TrieNode* next_node : node->links) { | ||
int next_idx = idx + 1; | ||
if (_search(word, next_idx, next_node)) return true; | ||
} | ||
return false; | ||
} | ||
} | ||
}; | ||
|
||
/** | ||
* Your WordDictionary object will be instantiated and called as such: | ||
* WordDictionary* obj = new WordDictionary(); | ||
* obj->addWord(word); | ||
* bool param_2 = obj->search(word); | ||
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/** | ||
* 풀이 | ||
* - 아래와 같은 배열 memo를 이용하여 이중 반복문을 실행하는 풀이입니다 | ||
* - memo[i]: nums[i]로 끝나는 subsequence 중에서 길이가 가장 긴 subsequence의 길이 | ||
* | ||
* Big O | ||
* - N: 배열 nums의 길이 | ||
* - Time complexity: O(N^2) | ||
* - Space complexity: O(N) | ||
*/ | ||
|
||
class Solution { | ||
public: | ||
int lengthOfLIS(vector<int>& nums) { | ||
vector<int> memo; | ||
memo.push_back(1); | ||
|
||
int res = 1; | ||
for (int i = 1; i < nums.size(); ++i) { | ||
int tmp = 1; | ||
for (int j = 0; j < i; ++j) { | ||
if (nums[j] < nums[i]) tmp = max(tmp, memo[j] + 1); | ||
} | ||
memo.push_back(tmp); | ||
res = max(res, tmp); | ||
} | ||
|
||
return res; | ||
} | ||
}; | ||
|
||
/** | ||
* 풀이 | ||
* - wikipedia의 pseudo code를 참고하였습니다 | ||
* 달레님 블로그에 실린 풀이를 통해서 훨씬 간단하게 문제에서 요구하는 바를 구할 수 있으므로, 문제의 풀이만을 원하신다면 달레님 블로그를 추천드리고 | ||
* 좀 더 general하고 확장성 있는 알고리즘에 대해 궁금하신 분들께서는 wiki도 읽어보시는 걸 추천드립니다 (이해하는 데에는 시간이 좀 걸렸습니다) | ||
* | ||
* 제가 읽고 이해한 결과 wiki 풀이와 달레님 풀이의 비교는 다음과 같습니다 | ||
* | ||
* 공통점: 문제에서 요구하는 바를 구할 수 있음 (LIS의 길이) | ||
* 차이점: wiki 풀이는 문제에서 요구하는 바를 구하는 것에 비해 overkill입니다 (이 문제에서는 굳이 필요 없는 부분이 꽤 있음) | ||
* 대신, wiki 풀이는 확장성이 좀 더 넓은 풀이입니다 (각 길이에 해당하는 increasing subsequence를 재구축할 수 있음) | ||
* | ||
* 관심 있으신 분들께서는 한 번 읽어보시는 것을 추천합니다 :) | ||
* - 참고: https://en.wikipedia.org/wiki/Longest_increasing_subsequence#Efficient_algorithms | ||
obzva marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* | ||
* - memo[l]: 현재 nums[i]를 탐색중이라고 할 때, l <= i인 l에 대하여 | ||
* 길이가 l인 increasing subsequence들의 마지막 원소 중에서 | ||
* 가장 최소값인 nums[k]의 인덱스 k | ||
* nums를 순차적으로 탐색해 나감에 따라 계속 갱신되며 정렬된 상태를 유지하게 됩니다 (if x < y then nums[memo[x]] < nums[memo[y]]) | ||
* | ||
* - predec[i]: nums[i]를 마지막 원소로 하는 가장 긴 increasing subsequence에서 nums[i] 바로 앞에 오는 원소의 index | ||
* | ||
* - nums를 순차적으로 탐색하며, 현재 탐색 중인 nums[i]를 마지막 원소로 삼는 가장 긴 Increasing subsequence를 찾습니다 | ||
* 가장 긴 Increasing subsequence는 memo 배열에 대해 이분탐색을 실행하여 알아낼 수 있습니다 | ||
* | ||
* Big O | ||
* - N: 배열 nums의 길이 | ||
* | ||
* - Time complexity: O(NlogN) | ||
* - nums의 각 원소마다 memo에 대해 이분탐색을 실행하므로 N이 증가함에 따라 실행 시간은 N * logN 형태로 증가합니다 | ||
* - Space complexity: O(N) | ||
* - memo 배열의 크기는 N이 증가함에 따라 선형적으로 증가합니다 | ||
* (- predec 배열의 크기 또한 N이 증가함에 따라 선형적으로 증가합니다) | ||
*/ | ||
|
||
class Solution { | ||
public: | ||
int lengthOfLIS(vector<int>& nums) { | ||
int n = nums.size(); | ||
|
||
vector<int> memo(n + 1, -1); | ||
|
||
// vector<int> predec(n, -1); | ||
// 각 길이에 맞는 increasing subsequence를 재구축할 때 쓰입니다 | ||
|
||
int max_len = 0; | ||
for (int i = 0; i < nums.size(); ++i) { | ||
int lo = 1; | ||
int hi = max_len + 1; | ||
while (lo < hi) { | ||
int mid = lo + (hi - lo) / 2; | ||
if (nums[memo[mid]] < nums[i]) lo = mid + 1; | ||
else hi = mid; | ||
} | ||
// 위 이분탐색을 마치면 lo == hi인데 | ||
// lo (혹은 hi)가 의미하는 바는 `nums[i]가 마지막 원소인 increasing subsequence 중에 길이가 가장 긴 녀석의 길이` 입니다 | ||
int curr_len = lo; | ||
// 이해하기 쉽게끔 curr_len이라는 변수를 선언해줍니다 | ||
|
||
// predec[i] = memo[curr_len - 1]; | ||
// nums[i]가 마지막으로 오는 가장 긴 increasing subsequence에서 nums[i]의 바로 전 원소의 index를 기록해줍니다 | ||
// | ||
memo[curr_len] = i; | ||
|
||
if (curr_len > max_len) { | ||
// 만약 이전까지 찾았던 max_len보다 더 길이가 긴 increasing subsequence를 max_len | ||
max_len = curr_len; | ||
} | ||
} | ||
|
||
return max_len; | ||
|
||
// 길이 L짜리 increasing subsequence 중 하나를 재구축하려면 아래처럼 하면 됩니다 | ||
// [P...P[memo[L]], ..., P[P[memo[L]]], P[memo[L]] ,memo[L]] | ||
|
||
// vector<int> s(L, -1); | ||
// int k = memo[L]; | ||
// for (int i = L - 1; i >= 0; --i) { | ||
// s[i] = nums[k]; | ||
// k = predec[k]; | ||
// } | ||
} | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/** | ||
* 풀이 | ||
* - 탐색 방향을 90도씩 회전해나가면서 주어진 2차원 배열 matrix를 탐색합니다 | ||
* - 한계: 주어진 matrix를 변형하게 되며, 해당 변형을 피하기 위해서는 추가적인 공간 사용이 필요합니다 | ||
* | ||
* Big O | ||
* - M: 주어진 matrix의 행의 개수 | ||
* - N: 열의 개수 | ||
* | ||
* - Time complexity: O(MN) | ||
* - Space complexity: O(1) | ||
*/ | ||
|
||
class Solution { | ||
public: | ||
pair<int, int> rotate(pair<int, int> dir) { | ||
// 시계방향 90도 회전 | ||
// 행렬곱으로 구해줄 수 있습니다 | ||
// | 0 -1 | | dir.first | = | -dir.second | | ||
// | 1 0 | | dir.second | | dir.first | | ||
return {dir.second, -dir.first}; | ||
} | ||
|
||
pair<int, int> get_next(pair<int, int> curr, pair<int, int> dir) { | ||
return {curr.first + dir.first, curr.second + dir.second}; | ||
} | ||
|
||
vector<int> spiralOrder(vector<vector<int>>& matrix) { | ||
int m = matrix.size(); | ||
int n = matrix[0].size(); | ||
int cnt = m * n; | ||
|
||
pair<int, int> curr = {0, 0}; | ||
pair<int, int> curr_dir = {0, 1}; | ||
|
||
vector<int> res; | ||
|
||
while (cnt) { | ||
res.push_back(matrix[curr.first][curr.second]); | ||
|
||
matrix[curr.first][curr.second] = 101; // constraint 밖의 값 101로 방문 여부를 표시합니다 | ||
--cnt; | ||
|
||
pair<int, int> next = get_next(curr, curr_dir); | ||
|
||
if (0 > next.first || next.first >= m | ||
|| 0 > next.second || next.second >= n | ||
|| matrix[next.first][next.second] == 101) { | ||
curr_dir = rotate(curr_dir); | ||
curr = get_next(curr, curr_dir); | ||
} else { | ||
curr = next; | ||
} | ||
} | ||
|
||
return res; | ||
} | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* 풀이 | ||
* - stack 자료구조를 이용합니다 | ||
* | ||
* Big O | ||
* - N: 주어진 문자열 s의 길이 | ||
* | ||
* - Time complexity: O(N) | ||
* - 문자열 s 전체를 순회할 경우 실행시간은 N에 선형적으로 비례하여 증가합니다 | ||
* - Space complexity: O(N) | ||
* - "((((((...((((((" 와 같은 입력을 받으면 stack의 크기가 최대 N까지 증가합니다 | ||
*/ | ||
|
||
class Solution { | ||
public: | ||
bool isValid(string s) { | ||
stack<char> st; | ||
for (char ch : s) { | ||
if (ch == '(' || ch == '{' || ch == '[') { | ||
st.push(ch); | ||
} else { | ||
if (st.empty()) return false; | ||
else if (st.top() == '(' && ch == ')') st.pop(); | ||
else if (st.top() == '{' && ch == '}') st.pop(); | ||
else if (st.top() == '[' && ch == ']') st.pop(); | ||
else return false; | ||
} | ||
} | ||
return st.empty(); | ||
} | ||
}; |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.