Skip to content

Commit 8deb424

Browse files
[dolphinflow86] WEEK 13 Solutions (#2864)
* insert interval solution * lowest common ancestor of a binary search tree solution * kth smallest element in a bst solution * find median from data stream solution * serialize and deserialize binary tree solution * number of connected components in an undirected graph solution
1 parent f061f18 commit 8deb424

6 files changed

Lines changed: 196 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# N is the number of elements added to the data stream.
2+
# TC: O(log N) for addNum, O(1) for findMedian
3+
# SC: O(N) - stores elements split into two heaps
4+
5+
import heapq
6+
7+
8+
class MedianFinder:
9+
10+
def __init__(self):
11+
self.small = [] # max-heap (store negative values)
12+
self.large = [] # min-heap
13+
14+
def addNum(self, num: int) -> None:
15+
heapq.heappush(self.small, -num)
16+
17+
if self.small and self.large and (-self.small[0] > self.large[0]):
18+
val = -heapq.heappop(self.small)
19+
heapq.heappush(self.large, val)
20+
21+
if len(self.small) > len(self.large) + 1:
22+
val = -heapq.heappop(self.small)
23+
heapq.heappush(self.large, val)
24+
25+
if len(self.large) > len(self.small):
26+
val = heapq.heappop(self.large)
27+
heapq.heappush(self.small, -val)
28+
29+
def findMedian(self) -> float:
30+
if len(self.small) > len(self.large):
31+
return float(-self.small[0])
32+
return (-self.small[0] + self.large[0]) / 2.0

‎insert-interval/dolphinflow86.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# N is the number of intervals.
2+
# TC: O(N) - single pass through intervals array
3+
# SC: O(N) - stores result intervals list
4+
5+
6+
class Solution:
7+
8+
def insert(self, intervals, newInterval):
9+
result = []
10+
i = 0
11+
n = len(intervals)
12+
13+
while i < n and intervals[i][1] < newInterval[0]:
14+
result.append(intervals[i])
15+
i += 1
16+
17+
while i < n and intervals[i][0] <= newInterval[1]:
18+
newInterval[0] = min(newInterval[0], intervals[i][0])
19+
newInterval[1] = max(newInterval[1], intervals[i][1])
20+
i += 1
21+
22+
result.append(newInterval)
23+
24+
while i < n:
25+
result.append(intervals[i])
26+
i += 1
27+
28+
return result
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# H is the height of the BST, and K is the target rank.
2+
# TC: O(H + K) - in-order traversal stops after visiting K elements
3+
# SC: O(H) - stack memory for in-order traversal recursion/loop
4+
5+
# Definition for a binary tree node.
6+
# class TreeNode:
7+
# def __init__(self, val=0, left=None, right=None):
8+
# self.val = val
9+
# self.left = left
10+
# self.right = right
11+
12+
13+
class Solution:
14+
15+
def kthSmallest(self, root, k: int) -> int:
16+
stack = []
17+
curr = root
18+
19+
while curr or stack:
20+
while curr:
21+
stack.append(curr)
22+
curr = curr.left
23+
24+
curr = stack.pop()
25+
k -= 1
26+
27+
if k == 0:
28+
return curr.val
29+
30+
curr = curr.right
31+
32+
return -1
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# H is the height of the binary search tree.
2+
# TC: O(H) - traverses down tree height
3+
# SC: O(1) - uses iterative traversal without recursion stack
4+
5+
# Definition for a binary tree node.
6+
# class TreeNode:
7+
# def __init__(self, x):
8+
# self.val = x
9+
# self.left = None
10+
# self.right = None
11+
12+
13+
class Solution:
14+
15+
def lowestCommonAncestor(self, root, p, q):
16+
curr = root
17+
18+
while curr:
19+
if p.val < curr.val and q.val < curr.val:
20+
curr = curr.left
21+
elif p.val > curr.val and q.val > curr.val:
22+
curr = curr.right
23+
else:
24+
return curr
25+
26+
return None
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# n is the number of nodes, and E is the number of edges.
2+
# TC: O(V + E * alpha(V)) - near linear time with path compression Union-Find
3+
# SC: O(V) - parent and rank arrays for Union-Find
4+
5+
6+
class Solution:
7+
8+
def countComponents(self, n: int, edges) -> int:
9+
parent = list(range(n))
10+
rank = [1] * n
11+
12+
def find(node):
13+
if parent[node] != node:
14+
parent[node] = find(parent[node])
15+
return parent[node]
16+
17+
def union(n1, n2):
18+
p1, p2 = find(n1), find(n2)
19+
if p1 == p2:
20+
return 0
21+
22+
if rank[p1] > rank[p2]:
23+
parent[p2] = p1
24+
rank[p1] += rank[p2]
25+
else:
26+
parent[p1] = p2
27+
rank[p2] += rank[p1]
28+
return 1
29+
30+
components = n
31+
for u, v in edges:
32+
components -= union(u, v)
33+
34+
return components
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# N is the number of nodes in the binary tree.
2+
# TC: O(N) - visits each node once during serialization and deserialization
3+
# SC: O(N) - stores node values and recursion stack
4+
5+
# Definition for a binary tree node.
6+
# class TreeNode(object):
7+
# def __init__(self, x):
8+
# self.val = x
9+
# self.left = None
10+
# self.right = None
11+
12+
13+
class Codec:
14+
15+
def serialize(self, root):
16+
vals = []
17+
18+
def dfs(node):
19+
if not node:
20+
vals.append("N")
21+
return
22+
vals.append(str(node.val))
23+
dfs(node.left)
24+
dfs(node.right)
25+
26+
dfs(root)
27+
return ",".join(vals)
28+
29+
def deserialize(self, data):
30+
vals = data.split(",")
31+
self.i = 0
32+
33+
def dfs():
34+
if vals[self.i] == "N":
35+
self.i += 1
36+
return None
37+
38+
node = TreeNode(int(vals[self.i]))
39+
self.i += 1
40+
node.left = dfs()
41+
node.right = dfs()
42+
return node
43+
44+
return dfs()

0 commit comments

Comments
 (0)