-
-
Notifications
You must be signed in to change notification settings - Fork 335
[hwi-middle] WEEK 15 solutions #2636
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| class Solution | ||
| { | ||
| public: | ||
| string alienOrder(vector<string>& words) | ||
| { | ||
| unordered_map<char, unordered_set<char>> graph; // 해당 문자 뒤에 와야하는 문자들 | ||
| unordered_map<char, int> state; // DFS 방문 상태: 0(방문 안함), 1(방문 중), 2(방문 완료) | ||
|
|
||
| // 모든 문자를 그래프에 넣음 | ||
| for (const auto& word : words) | ||
| { | ||
| for (char c : word) | ||
| { | ||
| graph[c]; | ||
| } | ||
| } | ||
|
|
||
| // 인접한 문자 비교 | ||
| for (int i = 0; i < words.size() - 1; ++i) | ||
| { | ||
| string& a = words[i]; | ||
| string& b = words[i + 1]; | ||
|
|
||
| int len = min(a.size(), b.size()); | ||
|
|
||
| int j = 0; | ||
| while (j < len && a[j] == b[j]) | ||
| { | ||
| ++j; | ||
| } | ||
|
|
||
| // 마지막까지 동일한 경우 | ||
| if (j == len) | ||
| { | ||
| // 사전순인데 앞 단어가 더 길면 규칙 위반 | ||
| if (a.size() > b.size()) | ||
| { | ||
| return ""; | ||
| } | ||
|
|
||
| // 정상이지만 정보가 없음 | ||
| continue; | ||
| } | ||
|
|
||
| // 다른 문자를 찾은 경우 (그 부분만 의미있음) | ||
| graph[a[j]].insert(b[j]); | ||
| } | ||
|
|
||
| string result; | ||
|
|
||
| // 이제 위상정렬 -> 후위순회 dfs 후 순서 뒤집기 | ||
| function<bool(char)> dfs = [&](char node) | ||
| { | ||
| if (state[node] == 1) | ||
| { | ||
| return false; // 사이클 | ||
| } | ||
|
|
||
| if (state[node] == 2) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| state[node] = 1; | ||
|
|
||
| for (char next : graph[node]) | ||
| { | ||
| if (!dfs(next)) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| state[node] = 2; | ||
| result.push_back(node); | ||
|
|
||
| return true; | ||
| }; | ||
|
|
||
| for (auto& [node, _] : graph) | ||
| { | ||
| if (state[node] == 0) | ||
| { | ||
| if (!dfs(node)) | ||
| { | ||
| return ""; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| reverse(result.begin(), result.end()); | ||
|
|
||
| return result; | ||
| } | ||
| }; |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 중위 배열에서 루트 위치를 찾기 위해 find()를 호출하는 부분이 전체 재귀마다 선형 탐색을 수행하므로 최악의 경우 O(n^2) 시간 복잡도를 가집니다. 공간은 재귀 호출 스택과 배열 슬라이스에 따른 것입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
|
|
||
| // 전위 순회의 첫 번째로 나오는 노드가 루트라는 성질을 활용 | ||
| // 중위 순회에서 루트를 찾아 좌우 구분 가능 | ||
| class Solution { | ||
| public: | ||
| TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { | ||
| return buildTreeWithSpan(span(preorder), span(inorder)); | ||
| } | ||
|
|
||
| TreeNode* buildTreeWithSpan(span<int> preorder, span<int> inorder) | ||
| { | ||
| if (preorder.size() == 0) | ||
| { | ||
| return nullptr; | ||
| } | ||
|
|
||
| int rootVal = preorder[0]; | ||
| TreeNode* rootNode = new TreeNode(rootVal); | ||
| if (preorder.size() == 1) | ||
| { | ||
| return rootNode; | ||
| } | ||
| int leftSubtreeSize = find(inorder.begin(), inorder.end(), rootVal) - inorder.begin(); | ||
| int n = inorder.size(); | ||
| span<int> leftPreorder = preorder.subspan(1, leftSubtreeSize); | ||
| span<int> leftInorder = inorder.subspan(0, leftSubtreeSize); | ||
| span<int> rightPreorder = preorder.subspan(leftSubtreeSize + 1, n - leftSubtreeSize - 1); | ||
| span<int> rightInorder = inorder.subspan(leftSubtreeSize + 1, n - leftSubtreeSize - 1); | ||
| rootNode->left = buildTreeWithSpan(leftPreorder, leftInorder); | ||
| rootNode->right = buildTreeWithSpan(rightPreorder, rightInorder); | ||
| return rootNode; | ||
| } | ||
| }; |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 각 위치에서 팰린드롬을 확장하는 방식으로, 전체 문자열 길이 n에 대해 최대 2n-1 위치에서 확장 시도하며, 확장 과정은 전체 문자열 길이의 합으로 제한되어 O(n) 시간입니다. 공간은 변환 문자열과 결과 저장에 따른 것입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // Editorial 참고 - 마나커 알고리즘 | ||
| class Solution { | ||
| public: | ||
| string longestPalindrome(string s) { | ||
| string s_prime = "#"; | ||
| for (char c : s) | ||
| { | ||
| s_prime += c; | ||
| s_prime += "#"; | ||
| } | ||
|
|
||
| int n = s_prime.length(); | ||
| vector<int> palindrome_radii(n, 0); | ||
| int center = 0; | ||
| int radius = 0; | ||
|
|
||
| for (int i = 0; i < n; i++) | ||
| { | ||
| int mirror = 2 * center - i; | ||
|
|
||
| if (i < radius) | ||
| { | ||
| palindrome_radii[i] = min(radius - i, palindrome_radii[mirror]); | ||
| } | ||
|
|
||
| while (i + 1 + palindrome_radii[i] < n && | ||
| i - 1 - palindrome_radii[i] >= 0 && | ||
| s_prime[i + 1 + palindrome_radii[i]] == s_prime[i - 1 - palindrome_radii[i]] | ||
| ) | ||
| { | ||
| palindrome_radii[i]++; | ||
| } | ||
|
|
||
| if (i + palindrome_radii[i] > radius) | ||
| { | ||
| center = i; | ||
| radius = i + palindrome_radii[i]; | ||
| } | ||
| } | ||
|
|
||
| int max_length = 0; | ||
| int center_index = 0; | ||
| for (int i = 0; i < n; i++) | ||
| { | ||
| if (palindrome_radii[i] > max_length) | ||
| { | ||
| max_length = palindrome_radii[i]; | ||
| center_index = i; | ||
| } | ||
| } | ||
|
|
||
| int start_index = (center_index - max_length) / 2; | ||
| string longest_palindrome = s.substr(start_index, max_length); | ||
|
|
||
| return longest_palindrome; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class Solution { | ||
| public: | ||
| void rotate(vector<vector<int>>& matrix) { | ||
| int n = matrix.size(); | ||
| // transpose 후 뒤집으면 90도 회전 | ||
| for (int i = 0; i < n; ++i) | ||
| { | ||
| for (int j = i; j < n; ++j) | ||
| { | ||
| swap(matrix[i][j], matrix[j][i]); | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < n; ++i) | ||
| { | ||
| reverse(matrix[i].begin(), matrix[i].end()); | ||
| } | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /** | ||
| * Definition for a binary tree node. | ||
| * struct TreeNode { | ||
| * int val; | ||
| * TreeNode *left; | ||
| * TreeNode *right; | ||
| * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| * }; | ||
| */ | ||
| class Solution { | ||
| public: | ||
| bool isSubtree(TreeNode* root, TreeNode* subRoot) { | ||
| if (root == nullptr || subRoot == nullptr) | ||
| { | ||
| return root == subRoot; | ||
| } | ||
|
|
||
| if (isSameTree(root, subRoot)) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| return isSubtree(root->left, subRoot) | ||
| || isSubtree(root->right, subRoot); | ||
| } | ||
|
|
||
| bool isSameTree(TreeNode* a, TreeNode* b) | ||
| { | ||
| if (a == nullptr || b == nullptr) | ||
| { | ||
| return a == b; | ||
| } | ||
|
|
||
| if (a->val != b->val) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| return isSameTree(a->left, b->left) | ||
| && isSameTree(a->right, b->right); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 그래프와 DFS를 이용한 위상 정렬로 문자 순서를 결정하며, 모든 문자와 간선을 한 번씩 탐색하므로 시간 복잡도는 선형입니다. 공간 복잡도는 그래프 저장과 DFS 스택/상태 저장에 따른 것입니다.