Skip to content

Commit 8360357

Browse files
committed
add Find Median from Data Stream solution
1 parent 70d1d96 commit 8360357

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* [Problem]: [295] Find Median from Data Stream
3+
* (https://leetcode.com/problems/find-median-from-data-stream/description/)
4+
*/
5+
class Heap {
6+
private numbers: number[];
7+
private compare: (a: number, b: number) => boolean;
8+
9+
constructor(compare: (a: number, b: number) => boolean) {
10+
this.numbers = [];
11+
this.compare = compare;
12+
}
13+
14+
private getParentIdx(index: number) {
15+
return Math.floor((index - 1) / 2);
16+
}
17+
18+
private getLeftChildIdx(index: number) {
19+
return 2 * index + 1;
20+
}
21+
22+
private getRightChildIdx(index: number) {
23+
return 2 * index + 2;
24+
}
25+
26+
private swap(index1: number, index2: number): void {
27+
[this.numbers[index1], this.numbers[index2]] = [this.numbers[index2], this.numbers[index1]];
28+
}
29+
30+
private heapifyUp(index: number) {
31+
const parentIndex = this.getParentIdx(index);
32+
if (0 <= parentIndex && this.compare(this.numbers[index], this.numbers[parentIndex])) {
33+
this.swap(index, parentIndex);
34+
this.heapifyUp(parentIndex);
35+
}
36+
}
37+
38+
private heapifyDown(index: number): void {
39+
const leftChildIndex = this.getLeftChildIdx(index);
40+
const rightChildIndex = this.getRightChildIdx(index);
41+
let largestIndex = index;
42+
43+
if (
44+
leftChildIndex < this.numbers.length &&
45+
this.compare(this.numbers[leftChildIndex], this.numbers[largestIndex])
46+
) {
47+
largestIndex = leftChildIndex;
48+
}
49+
50+
if (
51+
rightChildIndex < this.numbers.length &&
52+
this.compare(this.numbers[rightChildIndex], this.numbers[largestIndex])
53+
) {
54+
largestIndex = rightChildIndex;
55+
}
56+
57+
if (largestIndex !== index) {
58+
this.swap(index, largestIndex);
59+
this.heapifyDown(largestIndex);
60+
}
61+
}
62+
63+
insert(number: number) {
64+
this.numbers.push(number);
65+
this.heapifyUp(this.numbers.length - 1);
66+
}
67+
68+
pop() {
69+
if (this.numbers.length === 0) {
70+
return null;
71+
}
72+
73+
if (this.numbers.length === 1) {
74+
return this.numbers.pop()!;
75+
}
76+
77+
const root = this.numbers[0];
78+
this.numbers[0] = this.numbers.pop()!;
79+
this.heapifyDown(0);
80+
81+
return root;
82+
}
83+
84+
peek() {
85+
return this.numbers.length > 0 ? this.numbers[0] : null;
86+
}
87+
88+
size(): number {
89+
return this.numbers.length;
90+
}
91+
}
92+
93+
class MedianFinder {
94+
private smallHeap: Heap;
95+
private largeHeap: Heap;
96+
97+
constructor() {
98+
this.smallHeap = new Heap((a, b) => a > b);
99+
this.largeHeap = new Heap((a, b) => a < b);
100+
}
101+
102+
//시간복잡도 O(log n)
103+
addNum(num: number): void {
104+
this.smallHeap.insert(num);
105+
this.largeHeap.insert(this.smallHeap.pop()!);
106+
107+
if (this.smallHeap.size() < this.largeHeap.size()) {
108+
this.smallHeap.insert(this.largeHeap.pop()!);
109+
}
110+
}
111+
112+
//시간복잡도 O(1)
113+
findMedian(): number {
114+
if (this.smallHeap.size() > this.largeHeap.size()) {
115+
return this.smallHeap.peek()!;
116+
} else {
117+
return (this.smallHeap.peek()! + this.largeHeap.peek()!) / 2;
118+
}
119+
}
120+
}
121+
122+
/**
123+
* Your MedianFinder object will be instantiated and called as such:
124+
* var obj = new MedianFinder()
125+
* obj.addNum(num)
126+
* var param_2 = obj.findMedian()
127+
*/

0 commit comments

Comments
 (0)