-
-
Notifications
You must be signed in to change notification settings - Fork 334
[hwi-middle] WEEK 14 solutions #2626
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,51 @@ | ||
| /** | ||
| * 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: | ||
| vector<vector<int>> levelOrder(TreeNode* root) { | ||
| vector<vector<int>> v; | ||
| if (root == nullptr) | ||
| { | ||
| return v; | ||
| } | ||
|
|
||
| // BFS로 해결 | ||
| queue<pair<TreeNode*, int>> q; | ||
| q.push({root, 0}); | ||
| while (!q.empty()) | ||
| { | ||
| TreeNode* cur; | ||
| int h; | ||
| tie(cur, h) = q.front(); | ||
| q.pop(); | ||
|
|
||
| if (v.size() == h) | ||
| { | ||
| v.push_back(vector<int>()); | ||
| } | ||
|
|
||
| v[h].push_back(cur->val); | ||
|
|
||
| if (cur->left != nullptr) | ||
| { | ||
| q.push({cur->left, h + 1}); | ||
| } | ||
|
|
||
| if (cur->right != nullptr) | ||
| { | ||
| q.push({cur->right, h + 1}); | ||
| } | ||
| } | ||
|
|
||
| return v; | ||
| } | ||
| }; |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 단일 반복문으로 i & (i - 1) 연산을 통해 이전 값에 1을 더하는 방식으로 계산하며, 모든 수를 한 번씩 처리한다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| class Solution { | ||
| public: | ||
| vector<int> countBits(int n) { | ||
| // i & (i - 1)은 가장 오른쪽 비트 1을 지운다는 성질을 이용 | ||
| vector<int> ans(n + 1); // ans[0]은 0으로 초기화 | ||
| for (int i = 1; i <= n; ++i) | ||
| { | ||
| ans[i] = ans[i & (i - 1)] + 1; | ||
| } | ||
|
|
||
| return ans; | ||
| } | ||
| }; |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 두 개의 독립된 DP 계산을 통해 최적 해를 구하며, 각각의 경우에 대해 배열을 한 번씩 순회한다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| class Solution { | ||
| public: | ||
| int rob(vector<int>& nums) { | ||
| if (nums.size() == 1) | ||
| { | ||
| return nums[0]; | ||
| } | ||
|
|
||
| // 1번째 집과 n번째 집이 이웃하므로, [1, n)과 (1, n]에 대해 탐색 후 최댓값 반환 | ||
| return max(sol(span(nums).subspan(0, nums.size() - 1)), sol(span(nums).subspan(1))); | ||
| } | ||
|
|
||
| int sol(span<int> nums) { | ||
| int len = nums.size() + 1; | ||
| vector<int> d(len); | ||
| d[0] = 0; | ||
| d[1] = nums[0]; | ||
| for(int i = 2; i < len; ++i) | ||
| { | ||
| d[i] = max(d[i - 1], d[i - 2] + nums[i - 1]); | ||
| } | ||
|
|
||
| return d[len - 1]; | ||
| } | ||
| }; |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 이중 루프로 회의실을 찾기 때문에 최악의 경우 O(n^2) 시간이 소요되며, 회의실 리스트는 최대 n개까지 유지한다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| class Solution { | ||
| public: | ||
| int minMeetingRooms(vector<vector<int>>& intervals) { | ||
| // 시작 시간이 빠른 순으로 정렬 | ||
| int n = intervals.size(); | ||
| sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b) | ||
| { | ||
| return a[0] < b[0]; | ||
| }); | ||
|
|
||
| // 회의실이 부족할 때 마다 하나씩 추가 | ||
| // rooms에는 각 회의실을 마지막으로 이용한 회의의 종료 시간이 들어있음 | ||
| vector<int> rooms; | ||
| rooms.push_back({intervals[0][1]}); | ||
|
|
||
| for (int i = 1; i < n; ++i) | ||
| { | ||
| bool found = false; | ||
| for (auto& room : rooms) | ||
| { | ||
| // 빈 회의실을 찾은 경우 | ||
| if (room <= intervals[i][0]) | ||
| { | ||
| room = intervals[i][1]; | ||
| found = true; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| // 빈 회의실을 찾지 못한 경우 | ||
| if (!found) | ||
| { | ||
| rooms.push_back(intervals[i][1]); | ||
| } | ||
| } | ||
|
|
||
| return rooms.size(); | ||
| } | ||
| }; |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 트라이를 이용한 DFS로 효율적으로 탐색하며, 불필요한 경로를 제거하는 최적화도 포함되어 있다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| class Solution { | ||
| private: | ||
| // 트라이(Trie)를 활용 | ||
| struct Node | ||
| { | ||
| bool isWord = false; | ||
| Node* children[26]; | ||
| Node() : isWord(false) | ||
| { | ||
| fill(children, children + 26, nullptr); | ||
| } | ||
|
|
||
| bool isEmpty() | ||
| { | ||
| for (int i = 0; i < 26; ++i) | ||
| { | ||
| if (children[i] != nullptr) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| }; | ||
|
|
||
| // 각 노드는 배열로 관리 | ||
| static constexpr size_t POOL_SIZE = 300001; | ||
| Node pool[POOL_SIZE]; | ||
| int poolIdx = 0; | ||
|
|
||
| Node* newNode() | ||
| { | ||
| pool[poolIdx] = Node(); | ||
| return &pool[poolIdx++]; | ||
| } | ||
|
|
||
| Node* root; | ||
| vector<string> ans; | ||
| int row; | ||
| int col; | ||
|
|
||
| public: | ||
| vector<string> findWords(vector<vector<char>>& board, vector<string>& words) { | ||
| // 트라이 구성 시작 | ||
| poolIdx = 0; | ||
| ans.clear(); | ||
| root = newNode(); | ||
| for (auto& word : words) | ||
| { | ||
| Node* cur = root; | ||
| for (auto ch : word) | ||
| { | ||
| auto& child = cur->children[ch - 'a']; | ||
| if (child == nullptr) | ||
| { | ||
| child = newNode(); | ||
| } | ||
|
|
||
| cur = child; | ||
| } | ||
|
|
||
| cur->isWord = true; | ||
| } | ||
|
|
||
| // 한 칸씩 탐색 시작 | ||
| row = board.size(); | ||
| col = board[0].size(); | ||
| for (int r = 0; r < row; ++r) | ||
| { | ||
| for (int c = 0; c < col; ++c) | ||
| { | ||
| string s = ""; | ||
| solve(board, root, s, r, c); | ||
| } | ||
| } | ||
|
|
||
| return ans; | ||
| } | ||
|
|
||
| void solve(vector<vector<char>>& board, Node*& node, string& s, int r, int c) | ||
| { | ||
| // 경로가 제거된 경우 | ||
| if (node == nullptr) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // 범위를 벗어난 경우 | ||
| if (r < 0 || r >= row || c < 0 || c >= col) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // 이미 방문한 경우 | ||
| char ch = board[r][c]; | ||
| if (ch == '?') | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // 트라이에 이 문자가 없는 경우 (찾을 단어에 포함되지 않음) | ||
| if (node->children[ch - 'a'] == nullptr) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // 이 문자가 하나의 단어를 구성하는 경우 | ||
| if (node->children[ch - 'a']->isWord) | ||
| { | ||
| s.push_back(ch); | ||
| ans.push_back(s); | ||
| s.pop_back(); | ||
| node->children[ch - 'a']->isWord = false; // 중복 마킹 방지 | ||
| } | ||
|
|
||
| board[r][c] = '?'; // 이미 방문한 곳으로 돌아오지 않도록 입력으로 들어오지 않는 문자로 치환 | ||
|
|
||
| // 상하좌우 탐색 | ||
| static int dr[4] = { 1, 0, -1, 0 }; | ||
| static int dc[4] = { 0, 1, 0, -1 }; | ||
|
|
||
| for (int dir = 0; dir < 4; ++dir) | ||
| { | ||
| int nr = r + dr[dir]; | ||
| int nc = c + dc[dir]; | ||
| s.push_back(ch); | ||
| solve(board, node->children[ch - 'a'], s, nr, nc); | ||
| s.pop_back(); | ||
| } | ||
|
|
||
| board[r][c] = ch; // 원래 문자로 되돌리기 | ||
|
|
||
| // 더 이상 탐색이 필요 없는 곳은 경로 자체를 제거 | ||
| // 일단 자식 먼저 판단 | ||
| Node*& child = node->children[ch - 'a']; | ||
| if (child != nullptr && !child->isWord && child->isEmpty()) | ||
| { | ||
| child = nullptr; | ||
| } | ||
|
|
||
| // 자신도 지울 수 있으면 지움 | ||
| if (!node->isWord && node->isEmpty()) | ||
| { | ||
| node = nullptr; | ||
| } | ||
| } | ||
| }; |
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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 큐를 이용한 BFS로 모든 노드를 한 번씩 방문하며, 노드 수에 비례하는 공간이 필요하다.