Skip to content

Commit 23f4652

Browse files
authored
Merge pull request #1612 from Jeehay28/main
[Jeehay28] WEEK 13 Solutions
2 parents d198ece + 778edbb commit 23f4652

File tree

4 files changed

+305
-0
lines changed

4 files changed

+305
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
class MedianFinder {
2+
// [1, 2, 3, 4, 5, 6]
3+
private lower: MaxHeap; // max heap [3, 2, 1]
4+
private upper: MinHeap; // min heap [4, 5, 6]
5+
6+
constructor() {
7+
this.upper = new MinHeap();
8+
this.lower = new MaxHeap();
9+
}
10+
11+
// TC: O(log n)
12+
// SC: O(n)
13+
addNum(num: number): void {
14+
if (this.upper.size() === 0 || this.upper.getRoot() <= num) {
15+
this.upper.insert(num);
16+
} else {
17+
this.lower.insert(num);
18+
}
19+
20+
// Balance
21+
if (this.lower.size() - this.upper.size() > 1) {
22+
this.upper.insert(this.lower.removeRoot());
23+
} else if (this.upper.size() - this.lower.size() > 1) {
24+
this.lower.insert(this.upper.removeRoot());
25+
}
26+
}
27+
28+
// TC: O(1)
29+
// SC: O(1)
30+
findMedian(): number {
31+
if (this.upper.size() === this.lower.size()) {
32+
return (this.upper.getRoot() + this.lower.getRoot()) / 2;
33+
} else if (this.upper.size() > this.lower.size()) {
34+
return this.upper.getRoot();
35+
} else {
36+
return this.lower.getRoot();
37+
}
38+
}
39+
}
40+
41+
/**
42+
* Your MedianFinder object will be instantiated and called as such:
43+
* var obj = new MedianFinder()
44+
* obj.addNum(num)
45+
* var param_2 = obj.findMedian()
46+
*/
47+
48+
class MinHeap {
49+
private heap: number[] = [];
50+
51+
size(): number {
52+
return this.heap.length;
53+
}
54+
55+
getRoot(): number {
56+
return this.heap[0];
57+
}
58+
59+
insert(num: number): void {
60+
this.heap.push(num);
61+
this.bubbleUp();
62+
}
63+
64+
removeRoot(): number {
65+
const top = this.heap[0];
66+
const end = this.heap.pop()!;
67+
68+
if (this.heap.length > 0) {
69+
this.heap[0] = end;
70+
this.bubbleDown();
71+
}
72+
73+
return top;
74+
}
75+
76+
// Fix after removal (downward)
77+
bubbleDown(): void {
78+
let idx = 0;
79+
const length = this.heap.length;
80+
const val = this.heap[0];
81+
82+
while (true) {
83+
let leftIdx = 2 * idx + 1;
84+
let rightIdx = 2 * idx + 2;
85+
let swap = idx;
86+
87+
if (leftIdx < length && this.heap[leftIdx] < this.heap[swap]) {
88+
swap = leftIdx;
89+
}
90+
91+
if (rightIdx < length && this.heap[rightIdx] < this.heap[swap]) {
92+
swap = rightIdx;
93+
}
94+
95+
if (swap === idx) break;
96+
97+
this.heap[idx] = this.heap[swap];
98+
this.heap[swap] = val;
99+
idx = swap;
100+
}
101+
}
102+
103+
// Fix after insert (upward)
104+
bubbleUp(): void {
105+
let idx = this.heap.length - 1;
106+
const val = this.heap[idx];
107+
// Heap as an array
108+
// left child: 2 * i + 1
109+
// right child: 2 * i + 2
110+
// parent: Math.floor((i-1) / 2)
111+
112+
while (idx > 0) {
113+
const parentIdx = Math.floor((idx - 1) / 2);
114+
const parent = this.heap[parentIdx];
115+
116+
if (val >= parent) break;
117+
118+
this.heap[parentIdx] = val;
119+
this.heap[idx] = parent;
120+
idx = parentIdx;
121+
}
122+
}
123+
}
124+
125+
class MaxHeap {
126+
private heap: number[] = [];
127+
128+
size(): number {
129+
return this.heap.length;
130+
}
131+
132+
getRoot(): number {
133+
return this.heap[0];
134+
}
135+
136+
insert(num: number): void {
137+
this.heap.push(num);
138+
this.bubbleUp();
139+
}
140+
141+
removeRoot(): number {
142+
const top = this.heap[0];
143+
const end = this.heap.pop()!;
144+
145+
if (this.heap.length > 0) {
146+
this.heap[0] = end;
147+
this.bubbleDown();
148+
}
149+
150+
return top;
151+
}
152+
153+
bubbleDown(): void {
154+
let idx = 0;
155+
const length = this.heap.length;
156+
const val = this.heap[0];
157+
158+
while (true) {
159+
let leftIdx = 2 * idx + 1;
160+
let rightIdx = 2 * idx + 2;
161+
let swap = idx;
162+
163+
if (leftIdx < length && this.heap[leftIdx] > this.heap[swap]) {
164+
swap = leftIdx;
165+
}
166+
167+
if (rightIdx < length && this.heap[rightIdx] > this.heap[swap]) {
168+
swap = rightIdx;
169+
}
170+
171+
if (swap === idx) break;
172+
173+
this.heap[idx] = this.heap[swap];
174+
this.heap[swap] = val;
175+
idx = swap;
176+
}
177+
}
178+
179+
bubbleUp(): void {
180+
let idx = this.heap.length - 1;
181+
const val = this.heap[idx];
182+
183+
while (idx > 0) {
184+
const parentIdx = Math.floor((idx - 1) / 2);
185+
const parent = this.heap[parentIdx];
186+
187+
if (val <= parent) break;
188+
189+
this.heap[parentIdx] = val;
190+
this.heap[idx] = parent;
191+
idx = parentIdx;
192+
}
193+
}
194+
}

insert-interval/Jeehay28.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// TC: O(n)
2+
// SC: O(n)
3+
function insert(intervals: number[][], newInterval: number[]): number[][] {
4+
const result: number[][] = [];
5+
const n = intervals.length;
6+
let i = 0;
7+
8+
// Add all intervals that come before newInterval
9+
while (i < n && intervals[i][1] < newInterval[0]) {
10+
result.push(intervals[i]);
11+
i++;
12+
}
13+
14+
// Merge all overlapping intervals with newInterval
15+
while (i < n && intervals[i][0] <= newInterval[1]) {
16+
newInterval[0] = Math.min(intervals[i][0], newInterval[0]);
17+
newInterval[1] = Math.max(intervals[i][1], newInterval[1]);
18+
i++;
19+
}
20+
21+
result.push(newInterval);
22+
23+
// Add remaining intervals after newInterval
24+
while (i < n) {
25+
result.push(intervals[i]);
26+
i++;
27+
}
28+
29+
return result;
30+
}
31+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class TreeNode {
2+
val: number;
3+
left: TreeNode | null;
4+
right: TreeNode | null;
5+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
6+
this.val = val === undefined ? 0 : val;
7+
this.left = left === undefined ? null : left;
8+
this.right = right === undefined ? null : right;
9+
}
10+
}
11+
12+
// TC: O(n)
13+
// SC: O(n)
14+
function kthSmallest(root: TreeNode | null, k: number): number {
15+
const result: number[] = [];
16+
const dfs = (node: TreeNode | null) => {
17+
if (!node) return;
18+
19+
dfs(node.left);
20+
result.push(node.val);
21+
dfs(node.right);
22+
};
23+
24+
dfs(root);
25+
26+
return result[k - 1];
27+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
class TreeNode {
2+
val: number;
3+
left: TreeNode | null;
4+
right: TreeNode | null;
5+
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
6+
this.val = val === undefined ? 0 : val;
7+
this.left = left === undefined ? null : left;
8+
this.right = right === undefined ? null : right;
9+
}
10+
}
11+
12+
// TC: O(n)
13+
// SC: O(1)
14+
function lowestCommonAncestor(
15+
root: TreeNode | null,
16+
p: TreeNode | null,
17+
q: TreeNode | null
18+
): TreeNode | null {
19+
if (!root || !p || !q) return null;
20+
21+
let node = root;
22+
23+
while (node) {
24+
if (node.val < p.val && node.val < q.val) {
25+
node = node.right!;
26+
} else if (node.val > p.val && node.val > q.val) {
27+
node = node.left!;
28+
} else {
29+
return node;
30+
}
31+
}
32+
33+
return null;
34+
}
35+
36+
37+
// TC: O(n)
38+
// SC: O(n)
39+
// function lowestCommonAncestor(
40+
// root: TreeNode | null,
41+
// p: TreeNode | null,
42+
// q: TreeNode | null
43+
// ): TreeNode | null {
44+
// if (!root || !p || !q) return null;
45+
46+
// if (p.val < root.val && q.val < root.val) {
47+
// return lowestCommonAncestor(root.left, p, q);
48+
// } else if (p.val > root.val && q.val > root.val) {
49+
// return lowestCommonAncestor(root.right, p, q);
50+
// } else {
51+
// return root;
52+
// }
53+
// }

0 commit comments

Comments
 (0)