Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions alien-dictionary/hwi-middle.cpp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Topological Sort, DFS
  • 설명: 이 코드는 문자 간 의존 관계를 그래프로 만들어 위상 정렬을 수행하며, DFS를 이용해 사이클 검증과 정렬을 진행합니다. 따라서 Topological Sort와 DFS 패턴이 적용됩니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(V + E)
Space O(V + E)

피드백: 그래프와 DFS를 이용한 위상 정렬로 문자 순서를 결정하며, 모든 문자와 간선을 한 번씩 탐색하므로 시간 복잡도는 선형입니다. 공간 복잡도는 그래프 저장과 DFS 스택/상태 저장에 따른 것입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

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;
}
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Divide and Conquer
  • 설명: 이 코드는 전위와 중위 순회 배열을 이용해 재귀적으로 트리를 분할하여 구성하는 방식으로, 문제를 작은 부분으로 나누어 해결하는 Divide and Conquer 패턴에 속합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n^2)
Space O(n)

피드백: 중위 배열에서 루트 위치를 찾기 위해 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;
}
};
57 changes: 57 additions & 0 deletions longest-palindromic-substring/hwi-middle.cpp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Manacher's Algorithm
  • 설명: 이 코드는 가장 긴 회문 문자열을 찾기 위해 Manacher's Algorithm을 사용하며, 중심 확장과 회전하는 인덱스 방식을 활용합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(n)

피드백: 각 위치에서 팰린드롬을 확장하는 방식으로, 전체 문자열 길이 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;
}
};
19 changes: 19 additions & 0 deletions rotate-image/hwi-middle.cpp
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());
}
}
};
44 changes: 44 additions & 0 deletions subtree-of-another-tree/hwi-middle.cpp
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);
}
};
Loading