Repository navigation
[dolphinflow86] WEEK 14 Solutions #2873
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
79aa594
ee96e20
3de674e
63c70a1
65a8348
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,37 @@ | ||
| # N is the total number of nodes in the binary tree. | ||
| # TC: O(N) - each node is visited and enqueued/dequeued once | ||
| # SC: O(N) - queue stores at most the maximum width of the tree (up to N / 2 nodes) | ||
|
|
||
| from collections import deque | ||
| from typing import List, Optional | ||
|
|
||
|
|
||
| # Definition for a binary tree node. | ||
| # class TreeNode: | ||
| # def __init__(self, val=0, left=None, right=None): | ||
| # self.val = val | ||
| # self.left = left | ||
| # self.right = right | ||
|
|
||
|
|
||
| class Solution: | ||
|
|
||
| def levelOrder(self, root: Optional["TreeNode"]) -> List[List[int]]: | ||
| if not root: | ||
| return [] | ||
|
|
||
| levels = [] | ||
| queue = deque([root]) | ||
|
|
||
| while queue: | ||
| level_vals = [] | ||
| for _ in range(len(queue)): | ||
| node = queue.popleft() | ||
| level_vals.append(node.val) | ||
| if node.left: | ||
| queue.append(node.left) | ||
| if node.right: | ||
| queue.append(node.right) | ||
| levels.append(level_vals) | ||
|
|
||
| return levels |
|
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. 🏷️ 알고리즘 패턴 분석counting-bits/dolphinflow86.py# N is the given integer.
# TC: O(N) - single pass from 0 to N using previous subproblem results
# SC: O(1) - auxiliary space (O(N) to store the result array)
from typing import List
class Solution:
def countBits(self, n: int) -> List[int]:
ans = [0] * (n + 1)
for i in range(1, n + 1):
ans[i] = ans[i >> 1] + (i & 1)
return ans
📊 시간/공간 복잡도 분석
피드백: i의 이진 표현의 최하위 비트를 제거한 값에 1의 개수를 더하는 DP 방식으로 각 i에 대해 답을 빠르게 구한다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # N is the given integer. | ||
| # TC: O(N) - single pass from 0 to N using previous subproblem results | ||
| # SC: O(1) - auxiliary space (O(N) to store the result array) | ||
|
|
||
| from typing import List | ||
|
|
||
|
|
||
| class Solution: | ||
|
|
||
| def countBits(self, n: int) -> List[int]: | ||
| ans = [0] * (n + 1) | ||
| for i in range(1, n + 1): | ||
| ans[i] = ans[i >> 1] + (i & 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. 🏷️ 알고리즘 패턴 분석house-robber-ii/dolphinflow86.py# N is the number of houses.
# TC: O(N) - two passes of linear house robber (excluding first or last house)
# SC: O(1) - constant auxiliary space tracking two variables for DP
from typing import List
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
if len(nums) <= 2:
return max(nums)
def rob_linear(houses: List[int]) -> int:
prev2, prev1 = 0, 0
for money in houses:
prev2, prev1 = prev1, max(prev1, prev2 + money)
return prev1
return max(rob_linear(nums[:-1]), rob_linear(nums[1:]))
📊 시간/공간 복잡도 분석
피드백: 두 개의 선형 다이내믹 프로그래밍 호출을 통해 원형 구조를 처리한다. 공간은 상수로 유지된다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # N is the number of houses. | ||
| # TC: O(N) - two passes of linear house robber (excluding first or last house) | ||
| # SC: O(1) - constant auxiliary space tracking two variables for DP | ||
|
|
||
| from typing import List | ||
|
|
||
|
|
||
| class Solution: | ||
|
|
||
| def rob(self, nums: List[int]) -> int: | ||
| if not nums: | ||
| return 0 | ||
| if len(nums) <= 2: | ||
| return max(nums) | ||
|
|
||
| def rob_linear(houses: List[int]) -> int: | ||
| prev2, prev1 = 0, 0 | ||
| for money in houses: | ||
| prev2, prev1 = prev1, max(prev1, prev2 + money) | ||
| return prev1 | ||
|
Comment on lines
+17
to
+20
Collaborator
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. prev2, prev1 을 사용하니 로직이 더 명확하게 보이네요. |
||
|
|
||
| return max(rob_linear(nums[:-1]), rob_linear(nums[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. 🏷️ 알고리즘 패턴 분석meeting-rooms-ii/dolphinflow86.py# N is the number of meeting intervals.
# TC: O(N log N) - sorting intervals by start time and maintaining a min-heap
# SC: O(N) - heap stores at most N end times in the worst case
import heapq
from typing import Any, List
class Solution:
def minMeetingRooms(self, intervals: List[Any]) -> int:
if not intervals:
return 0
# Support both List[List[int]] and List[Interval]
def get_interval(item):
if hasattr(item, "start") and hasattr(item, "end"):
return item.start, item.end
return item[0], item[1]
normalized = [get_interval(interval) for interval in intervals]
normalized.sort(key=lambda x: x[0])
min_heap = []
for start, end in normalized:
if min_heap and min_heap[0] <= start:
heapq.heappop(min_heap)
heapq.heappush(min_heap, end)
return len(min_heap)
min_meeting_rooms = minMeetingRooms
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(n log n) |
| Space | O(n) |
피드백: 회의 시작과 종료를 정렬하고, 종료 시점을 관리하는 힙으로 최댓 필요 방의 수를 계산한다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.minMeetingRooms — Time: O(n log n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(n log n) |
| Space | O(n) |
피드백: 헤더가 중복으로 보이는 주석적 라인으로 보이나 본문 기능에는 영향 없음.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # N is the number of meeting intervals. | ||
| # TC: O(N log N) - sorting intervals by start time and maintaining a min-heap | ||
| # SC: O(N) - heap stores at most N end times in the worst case | ||
|
|
||
| import heapq | ||
| from typing import Any, List | ||
|
|
||
|
|
||
| class Solution: | ||
|
|
||
| def minMeetingRooms(self, intervals: List[Any]) -> int: | ||
| if not intervals: | ||
| return 0 | ||
|
|
||
| # Support both List[List[int]] and List[Interval] | ||
| def get_interval(item): | ||
| if hasattr(item, "start") and hasattr(item, "end"): | ||
| return item.start, item.end | ||
| return item[0], item[1] | ||
|
|
||
| normalized = [get_interval(interval) for interval in intervals] | ||
| normalized.sort(key=lambda x: x[0]) | ||
|
|
||
| min_heap = [] | ||
| for start, end in normalized: | ||
| if min_heap and min_heap[0] <= start: | ||
| heapq.heappop(min_heap) | ||
| heapq.heappush(min_heap, end) | ||
|
|
||
| return len(min_heap) | ||
|
|
||
| min_meeting_rooms = minMeetingRooms |
|
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. 🏷️ 알고리즘 패턴 분석word-search-ii/dolphinflow86.py# M, N are dimensions of the board, W is the number of words, and L is the maximum length of a word.
# TC: O(W * L + M * N * 3^(L - 1)) - building Trie takes O(W * L); backtracking explores at most 3 directions after first step up to depth L
# SC: O(W * L) - Trie storage for all words and recursion stack depth up to L
from typing import List
class TrieNode:
def __init__(self):
self.children = {}
self.word = None
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
root = TrieNode()
for word in words:
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.word = word
rows, cols = len(board), len(board[0])
result = []
def dfs(r: int, c: int, parent: TrieNode):
char = board[r][c]
curr_node = parent.children.get(char)
if not curr_node:
return
if curr_node.word:
result.append(curr_node.word)
curr_node.word = None
board[r][c] = "#" # mark visited
for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc] != "#":
if board[nr][nc] in curr_node.children:
dfs(nr, nc, curr_node)
board[r][c] = char # backtrack
# Prune leaf nodes to accelerate search
if not curr_node.children:
del parent.children[char]
for r in range(rows):
for c in range(cols):
if board[r][c] in root.children:
dfs(r, c, root)
return result
📊 시간/공간 복잡도 분석
피드백: 전형적인 Trie+DFS 접근으로 여러 단어를 한 번에 탐색한다. 백트래킹과 트라이 가지치기로 실사용에서 효율을 높인다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # M, N are dimensions of the board, W is the number of words, and L is the maximum length of a word. | ||
| # TC: O(W * L + M * N * 3^(L - 1)) - building Trie takes O(W * L); backtracking explores at most 3 directions after first step up to depth L | ||
| # SC: O(W * L) - Trie storage for all words and recursion stack depth up to L | ||
|
|
||
| from typing import List | ||
|
|
||
|
|
||
| class TrieNode: | ||
|
|
||
| def __init__(self): | ||
| self.children = {} | ||
| self.word = None | ||
|
|
||
|
|
||
| class Solution: | ||
|
|
||
| def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: | ||
| root = TrieNode() | ||
| for word in words: | ||
| node = root | ||
| for char in word: | ||
| if char not in node.children: | ||
| node.children[char] = TrieNode() | ||
| node = node.children[char] | ||
| node.word = word | ||
|
|
||
| rows, cols = len(board), len(board[0]) | ||
| result = [] | ||
|
|
||
| def dfs(r: int, c: int, parent: TrieNode): | ||
| char = board[r][c] | ||
| curr_node = parent.children.get(char) | ||
| if not curr_node: | ||
| return | ||
|
|
||
| if curr_node.word: | ||
| result.append(curr_node.word) | ||
| curr_node.word = None | ||
|
|
||
| board[r][c] = "#" # mark visited | ||
|
|
||
| for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)): | ||
| nr, nc = r + dr, c + dc | ||
| if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc] != "#": | ||
| if board[nr][nc] in curr_node.children: | ||
| dfs(nr, nc, curr_node) | ||
|
|
||
| board[r][c] = char # backtrack | ||
|
|
||
| # Prune leaf nodes to accelerate search | ||
| if not curr_node.children: | ||
| del parent.children[char] | ||
|
|
||
| for r in range(rows): | ||
| for c in range(cols): | ||
| if board[r][c] in root.children: | ||
| dfs(r, c, root) | ||
|
|
||
| return result |
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.
🏷️ 알고리즘 패턴 분석
binary-tree-level-order-traversal/dolphinflow86.py
📊 시간/공간 복잡도 분석
피드백: 너비 우선 탐색으로 모든 노드를 한 번씩 방문하고 큐에 저장하므로 시간은 트리의 노드 수에 비례한다. 추가 공간은 큐와 결과 리스트에 의해 선형이다.
개선 제안: 현재 구현이 적절해 보입니다.