[dolphinflow86] WEEK 13 Solutions - #2864
Conversation
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
find-median-from-data-stream/dolphinflow86.py
# N is the number of elements added to the data stream.
# TC: O(log N) for addNum, O(1) for findMedian
# SC: O(N) - stores elements split into two heaps
import heapq
class MedianFinder:
def __init__(self):
self.small = [] # max-heap (store negative values)
self.large = [] # min-heap
def addNum(self, num: int) -> None:
heapq.heappush(self.small, -num)
if self.small and self.large and (-self.small[0] > self.large[0]):
val = -heapq.heappop(self.small)
heapq.heappush(self.large, val)
if len(self.small) > len(self.large) + 1:
val = -heapq.heappop(self.small)
heapq.heappush(self.large, val)
if len(self.large) > len(self.small):
val = heapq.heappop(self.large)
heapq.heappush(self.small, -val)
def findMedian(self) -> float:
if len(self.small) > len(self.large):
return float(-self.small[0])
return (-self.small[0] + self.large[0]) / 2.0- 패턴: Heap / Priority Queue, Hash Map / Hash Set
- 설명: 이 문제는 두 개의 힙을 이용해 데이터 스트림에서 중간값을 빠르게 찾는 구조로, 추가 시 힙 간 균형을 맞춰 중앙값을 O(1) 또는 O(log N)으로 반환합니다. 힙을 활용한 데이터 분리와 균형 유지가 핵심 패턴입니다.
📊 시간/공간 복잡도 분석
ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.
풀이 1: MedianFinder.addNum — Time: O(log n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(log n) |
| Space | O(n) |
피드백: 두 개의 힙으로 삽입 시나리오를 균형 있게 유지해 최악의 경우에도 로그 시간에 가운데값을 재조정합니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: MedianFinder.findMedian — Time: O(1) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(1) |
| Space | O(n) |
피드백: 상황에 따라 두 힙의 최댓값/최솟값을 활용해 상호 보완적으로 중간값을 계산합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
insert-interval/dolphinflow86.py
# N is the number of intervals.
# TC: O(N) - single pass through intervals array
# SC: O(N) - stores result intervals list
class Solution:
def insert(self, intervals, newInterval):
result = []
i = 0
n = len(intervals)
while i < n and intervals[i][1] < newInterval[0]:
result.append(intervals[i])
i += 1
while i < n and intervals[i][0] <= newInterval[1]:
newInterval[0] = min(newInterval[0], intervals[i][0])
newInterval[1] = max(newInterval[1], intervals[i][1])
i += 1
result.append(newInterval)
while i < n:
result.append(intervals[i])
i += 1
return result- 패턴: Two Pointers, Greedy, Binary Search
- 설명: 삽입하려는 구간과 기존 구간 배열을 스캔하며, 겹치지 않는 구간은 유지하고 겹치는 구간은 합쳐 하나의 구간으로 합치는 방식이다. 연속 탐색으로 정렬된 구간을 한 번의 순회로 처리하는 특징이 있다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 왼쪽, 중간, 오른쪽 파트를 순차적으로 처리하여 중복되는 구간을 하나의 구간으로 합칩니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
📊 dolphinflow86 님의 학습 현황이번 주 제출 문제
누적 학습 요약
문제 풀이 현황
🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다. 🔢 API 사용량 (gpt-5-nano)
|
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
kth-smallest-element-in-a-bst/dolphinflow86.py
# H is the height of the BST, and K is the target rank.
# TC: O(H + K) - in-order traversal stops after visiting K elements
# SC: O(H) - stack memory for in-order traversal recursion/loop
# 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 kthSmallest(self, root, k: int) -> int:
stack = []
curr = root
while curr or stack:
while curr:
stack.append(curr)
curr = curr.left
curr = stack.pop()
k -= 1
if k == 0:
return curr.val
curr = curr.right
return -1- 패턴: Binary Search, Monotonic Stack, Hash Map / Hash Set
- 설명: 이 코드는 이진 탐색 트리의 중위 순회를 이용해 k번째 원소를 찾는다(정렬된 순서를 얻기 위해). 스택을 이용한 비재귀 형태의 중위 순회는 특정 시점에서의 상태를 기록하기 위한 Monotonic Stack의 응용으로 볼 수 있으며, 이진 탐색 트리의 특성에 의존하므로 Binary Search의 맥락도 포함된다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(h) |
피드백: BST의 성질을 이용해 왼쪽으로 내려가며 순서를 카운트합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
lowest-common-ancestor-of-a-binary-search-tree/dolphinflow86.py
# H is the height of the binary search tree.
# TC: O(H) - traverses down tree height
# SC: O(1) - uses iterative traversal without recursion stack
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root, p, q):
curr = root
while curr:
if p.val < curr.val and q.val < curr.val:
curr = curr.left
elif p.val > curr.val and q.val > curr.val:
curr = curr.right
else:
return curr
return None- 패턴: Binary Search, Two Pointers
- 설명: 이 코드는 이진 탐색 트리에서 두 노드의 공통 조상을 찾기 위해 현재 노드 기준으로 p와 q의 값 비교를 통해 한 방향으로만 이동하는 방식으로 탐색한다. 트리의 높이에 비례하는 시간 복잡도이며, 상호 비교를 통한 목표 위치 탐색이 핵심이다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(h) |
| Space | O(1) |
피드백: 현재 노드 값을 비교해 좌우로 내려가며 LCA를 찾습니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
validate-binary-search-tree/dolphinflow86.py
# N is the number of nodes in the binary tree.
# TC: O(N) - visits each node at most once
# SC: O(H) - recursion stack space proportional to tree height H
# 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 isValidBST(self, root) -> bool:
def validate(node, low=float("-inf"), high=float("inf")):
if not node:
return True
if not (low < node.val < high):
return False
return validate(node.left, low, node.val) and validate(
node.right, node.val, high
)
return validate(root)- 패턴: Binary Search, Depth-First Search, Divide and Conquer
- 설명: 루트-왼쪽-오른쪽 트리를 재귀적으로 탐색하며 각 노드가 유효한 BST 구간(low, high) 내에 있는지 확인하고, 자식 노드에 대해 구간을 갱신하는 방식으로 문제를 풀이합니다. 각 노드는 한 번만 방문하므로 DFS 방식과 구간 분할(Divide and Conquer) 패턴에 해당합니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(h) |
피드백: 각 노드의 범위를 왼쪽/오른쪽 서브트리로 점진적으로 좁혀 검사합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
number-of-connected-components-in-an-undirected-graph/dolphinflow86.py
# n is the number of nodes, and E is the number of edges.
# TC: O(V + E * alpha(V)) - near linear time with path compression Union-Find
# SC: O(V) - parent and rank arrays for Union-Find
class Solution:
def countComponents(self, n: int, edges) -> int:
parent = list(range(n))
rank = [1] * n
def find(node):
if parent[node] != node:
parent[node] = find(parent[node])
return parent[node]
def union(n1, n2):
p1, p2 = find(n1), find(n2)
if p1 == p2:
return 0
if rank[p1] > rank[p2]:
parent[p2] = p1
rank[p1] += rank[p2]
else:
parent[p1] = p2
rank[p2] += rank[p1]
return 1
components = n
for u, v in edges:
components -= union(u, v)
return components- 패턴: Union Find
- 설명: 그래프의 연결 요소 수를 구하기 위해 서로 다른 정점을 하나의 집합으로 합치는 유니온-파인드(Union Find) 구조를 사용합니다. 간선 하나당 합치고, 성공적인 합치면 구성 요소 수를 감소시키는 방식이 특징입니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n + m) |
| Space | O(n) |
피드백: 가용한 모든 노드를 하나의 집합으로 시작하고, 간선을 따라 서로 다른 집합을 합치며 남은 서로 다른 루트의 개수를 반환합니다. 경로 압축과 랭크를 사용해 실질적 상수 계수도 낮습니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
serialize-and-deserialize-binary-tree/dolphinflow86.py
# N is the number of nodes in the binary tree.
# TC: O(N) - visits each node once during serialization and deserialization
# SC: O(N) - stores node values and recursion stack
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
vals = []
def dfs(node):
if not node:
vals.append("N")
return
vals.append(str(node.val))
dfs(node.left)
dfs(node.right)
dfs(root)
return ",".join(vals)
def deserialize(self, data):
vals = data.split(",")
self.i = 0
def dfs():
if vals[self.i] == "N":
self.i += 1
return None
node = TreeNode(int(vals[self.i]))
self.i += 1
node.left = dfs()
node.right = dfs()
return node
return dfs()- 패턴: Depth-First Search, Divide and Conquer
- 설명: 왔: 트리의 좌우를 깊이 우선으로 방문하며 직렬화/역직렬화를 재귀로 처리합니다. DFS를 이용한 순회와 순서를 이용한 분할 구성으로 구현되어 있습니다.
📊 시간/공간 복잡도 분석
ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.
풀이 1: Codec.serialize — Time: O(n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: DFS로 전체 트리를 순회하며 각 노드 값을 기록하고, null은 N으로 표시합니다. 직렬화 문자열의 길이는 노드 수에 비례합니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Codec.deserialize — Time: O(n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 입력 순서를 따라 재귀적으로 좌우 자식을 재생성합니다. 데이터 전체를 한 번 순회합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
19a1997 to
4aafa96
Compare
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
meeting-rooms/dolphinflow86.py
# N is the number of intervals.
# TC: O(N log N) - sorting the intervals by start time
# SC: O(1) - uses constant extra space
class Solution:
def canAttendMeetings(self, intervals: list[list[int]]) -> bool:
intervals.sort(key=lambda x: x[0])
for i in range(1, len(intervals)):
if intervals[i][0] < intervals[i - 1][1]:
return False
return True- 패턴: Sorting, Greedy, Binary Search
- 설명: 주어진 코드는 회의 시작 시점으로 정렬한 뒤 이전 회의의 종료 시간과 현재 회의 시작 시간을 비교하여 겹침을 확인합니다. 정렬을 활용해 간단히 선형 탐색으로 조건을 판단하는 패턴이며, 최적의 자원 배치를 찾는 관점에서 Greedy 성격도 보입니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n log n) |
| Space | O(1) |
피드백: 정렬에 의해 시간 복잡도가 결정되며, 추가 공간은 상수로 판단된다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
parkhojeong
left a comment
There was a problem hiding this comment.
이번 주도 수고하셨습니다. 이전 주차 풀이가 포함되어 있는데 제거 부탁드립니다~
답안 제출 문제
작성자 체크 리스트
검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!