Skip to content

Commit 8c983ee

Browse files
committed
Added 2 JS solutions for problem 703
1 parent 5fad87c commit 8c983ee

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
//////////////////////////////////////////////////////////////////////////////
2+
// Limited Size Min Heap
3+
// KthLargest.prototype.constructor
4+
// -> Time: Omega(n) Theta(n*log(k)) O(n*log(k))
5+
// -> Space: Theta(k) O(k)
6+
// KthLargest.prototype.add
7+
// -> Time: Omega(1) Theta(log(k)) O(log(k))
8+
// -> Space: Theta(1) O(1)
9+
// This solution works by creating a min heap of the `k` largest values. It is
10+
// the highest performing solution when `k` is noticeably different than
11+
// `nums.length`. If `k` is close to `nums.length` you would modify the
12+
// `MinHeap` constructor to heapify the `nums` array in linear time first and
13+
// then delete the minimum number from the heap until `heap.length` is equal
14+
// to `k`. The modified constructor's time complexity becomes
15+
// Omega(max((n-k)*log(n),n)), Theta(n*log(n)), and O(n*log(n)). While its
16+
// space complexity becomes Theta(n) and O(n).
17+
//////////////////////////////////////////////////////////////////////////////
18+
19+
class KthLargest {
20+
/**
21+
* @param {number} k
22+
* @param {number[]} nums
23+
* @constructor
24+
*/
25+
constructor(k, nums) {
26+
this.heap = new MinHeap(nums, k);
27+
}
28+
29+
/**
30+
* @param {number} val
31+
* @return {number}
32+
*/
33+
add(val) {
34+
this.heap.add(val);
35+
return this.heap.getMin();
36+
}
37+
}
38+
39+
class MinHeap {
40+
/**
41+
* @param {number[]} nums
42+
* @param {number} size
43+
* @constructor
44+
*/
45+
constructor(nums, size) {
46+
this.size = size;
47+
this.length = 0;
48+
this.heap = [];
49+
for (const num of nums) {
50+
this.add(num);
51+
}
52+
}
53+
54+
/**
55+
* @param {number} num
56+
* @return {void}
57+
*/
58+
add(num) {
59+
if (this.length < this.size) {
60+
++this.length;
61+
this.heap.push(num);
62+
this.siftUp(this.length - 1);
63+
} else if (num > this.heap[0]) {
64+
this.heap[0] = num;
65+
this.siftDown(0);
66+
}
67+
}
68+
69+
/**
70+
* @return {number}
71+
*/
72+
getMin() {
73+
return this.heap[0];
74+
}
75+
76+
/**
77+
* @param {number} i
78+
* @return {void}
79+
*/
80+
siftDown(i) {
81+
const length = this.length;
82+
const heap = this.heap;
83+
let k = i * 2 + 1;
84+
while (k < length) {
85+
if (k + 1 < length && heap[k + 1] < heap[k]) {
86+
++k;
87+
}
88+
if (heap[i] <= heap[k]) {
89+
return;
90+
}
91+
[ heap[i], heap[k] ] = [ heap[k], heap[i] ];
92+
i = k;
93+
k = i * 2 + 1;
94+
}
95+
}
96+
97+
/**
98+
* @param {number} i
99+
* @return {void}
100+
*/
101+
siftUp(i) {
102+
const heap = this.heap;
103+
let p = Math.floor((i - 1) / 2);
104+
while (i > 0 && heap[i] < heap[p]) {
105+
[ heap[i], heap[p] ] = [ heap[p], heap[i] ];
106+
i = p;
107+
p = Math.floor((i - 1) / 2);
108+
}
109+
}
110+
}
111+
112+
/**
113+
* Your KthLargest object will be instantiated and called as such:
114+
* var obj = new KthLargest(k, nums)
115+
* var param_1 = obj.add(val)
116+
*/
117+
118+
//////////////////////////////////////////////////////////////////////////////
119+
// Sort & Binary Search
120+
// KthLargest.prototype.constructor
121+
// -> Time: Omega(n) Theta(n*log(n)) O(n*log(n))
122+
// -> Space: Theta(n) O(n)
123+
// KthLargest.prototype.add
124+
// -> Time: Omega(1) Theta(log(n)) O(n)
125+
// -> Space: Theta(1) O(n)
126+
// This solution works by sorting the `nums` array and using binary search to
127+
// add new numbers to the sorted array. It is slower than the limited size
128+
// minimum heap solution.
129+
//////////////////////////////////////////////////////////////////////////////
130+
131+
class KthLargest {
132+
/**
133+
* @param {number} k
134+
* @param {number[]} nums
135+
* @constructor
136+
*/
137+
constructor(k, nums) {
138+
this.nums = nums.sort((a,b) => b - a);
139+
this.k = k;
140+
}
141+
142+
/**
143+
* @param {number} val
144+
* @return {number}
145+
*/
146+
add(val) {
147+
const nums = this.nums;
148+
let l = 0;
149+
let r = nums.length;
150+
while (l <= r) {
151+
const m = Math.floor((l + r) / 2);
152+
if (val === nums[m]) {
153+
l = m;
154+
break;
155+
}
156+
if (val < nums[m]) {
157+
l = m + 1;
158+
} else {
159+
r = m - 1;
160+
}
161+
}
162+
nums.splice(l, 0, val);
163+
return nums[this.k - 1];
164+
}
165+
}
166+
167+
/**
168+
* Your KthLargest object will be instantiated and called as such:
169+
* var obj = new KthLargest(k, nums)
170+
* var param_1 = obj.add(val)
171+
*/

0 commit comments

Comments
 (0)