Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 86dedc5

Browse files
committed
added all pending js solutions for heap datastructure
1 parent 53c3815 commit 86dedc5

File tree

5 files changed

+828
-0
lines changed

5 files changed

+828
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Using Quick Select Algorithm
3+
* https://www.youtube.com/watch?v=XEmy13g1Qxc
4+
* https://leetcode.com/problems/kth-largest-element-in-an-array/
5+
*/
6+
const findKthLargest = (nums, k) => {
7+
// find k distance from 0 index
8+
k = nums.length - k;
9+
// similar to quick sort
10+
return quickSelect(nums, 0, nums.length - 1, k);
11+
};
12+
13+
14+
// recursive function
15+
function quickSelect (nums, left, right, k) {
16+
let pivot = nums[right];
17+
let p = left;
18+
for (let i = left; i < right; i += 1) {
19+
if (nums[i] <= pivot) {
20+
// swap
21+
[nums[p], nums[i]] = [nums[i], nums[p]];
22+
p += 1;
23+
}
24+
}
25+
// swap
26+
[nums[p], nums[right]] = [nums[right], nums[p]];
27+
if (p > k) {
28+
return quickSelect(nums, left, p - 1, k);
29+
} else {
30+
if (p < k) {
31+
return quickSelect(nums, p + 1, right, k);
32+
} else {
33+
return nums[p];
34+
}
35+
}
36+
}
37+
38+
// TESTING
39+
console.log('Kth Largest element is:', findKthLargest([3,2,1,5,6,4], 2)); // 5
40+
console.log('Kth Largest element is:', findKthLargest([3,2,3,1,2,4,5,5,6], 4)); // 4
41+
42+
/**
43+
* NOTES
44+
* Three approaches
45+
* Approach #1 - Sort the array get the kth largest from behind, O(nlogn)
46+
* Approach #2 - Using MaxHeap - O(n) + O(klogn)
47+
* Approach #3 - Using Quick Select Algorithm
48+
* - Has an average Time complexity: O(n)
49+
* - Has a worst time complexity: O(n^2)
50+
* - For explanation, watch the video
51+
*/
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/**
2+
* Find Median in a Datastream
3+
* https://www.youtube.com/watch?v=itmhHWaHupI
4+
* https://leetcode.com/problems/find-median-from-data-stream/
5+
* Using Heap Datastructure (Maxheap and Minheap)
6+
*/
7+
class MedianFinder {
8+
constructor () {
9+
// create 2 heaps
10+
this.smallHeap = new Heap((a,b)=>(b-a)); //maxHeap
11+
this.largeHeap = new Heap((a,b)=>(a-b)); //minHeap
12+
}
13+
14+
addNum (num) {
15+
this.smallHeap.add(num);
16+
17+
// make sure every num small is <= every num in large
18+
if (this.smallHeap.size() > 0 &&
19+
this.largeHeap.size() > 0 &&
20+
this.smallHeap.peek() >
21+
this.largeHeap.peek()) {
22+
const el = this.smallHeap.remove();
23+
this.largeHeap.add(el);
24+
}
25+
26+
// check uneven size
27+
if (this.smallHeap.size() > this.largeHeap.size()+1) {
28+
const el = this.smallHeap.remove();
29+
this.largeHeap.add(el);
30+
}
31+
if (this.largeHeap.size() > this.smallHeap.size()+1) {
32+
const el = this.largeHeap.remove();
33+
this.smallHeap.add(el);
34+
}
35+
}
36+
37+
findMedian () {
38+
// check if we have odd number of elements
39+
if (this.smallHeap.size() > this.largeHeap.size()) {
40+
return this.smallHeap.peek();
41+
} else if (this.largeHeap.size() > this.smallHeap.size()) {
42+
return this.largeHeap.peek();
43+
}
44+
return ((this.smallHeap.peek() + this.largeHeap.peek())/2);
45+
}
46+
}
47+
48+
/**
49+
* egghead.io - Heap
50+
* https://github.com/basarat/algorithms/blob/master/src/heap/heap.ts
51+
*/
52+
53+
/**
54+
* Implements the heap data structure
55+
* A heap is used as a priority queue
56+
* Note: The default compare behavior gives you a min heap
57+
* @constructor ((a,b) => void) comparator, by default - ascending (a-b)
58+
*/
59+
class Heap {
60+
61+
62+
constructor(compareFn = undefined) {
63+
this.data = [];
64+
this.compareFn = compareFn && typeof compareFn === 'function' ? compareFn : (a, b) => (a - b);
65+
}
66+
67+
left(nodeIndex) {
68+
return (2 * nodeIndex) + 1;
69+
}
70+
71+
right(nodeIndex) {
72+
return (2 * nodeIndex) + 2;
73+
}
74+
75+
parent(nodeIndex) {
76+
return nodeIndex % 2 == 0
77+
? (nodeIndex - 2) / 2
78+
: (nodeIndex - 1) / 2;
79+
}
80+
81+
/**
82+
* Adds the given element into the heap in O(logn)
83+
*/
84+
add(element) {
85+
this.data.push(element);
86+
this.siftUp(this.data.length - 1);
87+
}
88+
89+
/**
90+
* Moves the nod at the given index up to its proper place in the heap.
91+
* @param index The index of the node to move up.
92+
*/
93+
siftUp(index) {
94+
let parent = this.parent(index);
95+
while (index > 0 && this.compareFn(this.data[parent], this.data[index]) > 0) {
96+
[this.data[parent], this.data[index]] = [this.data[index], this.data[parent]];
97+
index = parent;
98+
parent = this.parent(index);
99+
}
100+
}
101+
102+
/**
103+
* Retrieves and removes the root element of this heap in O(logn)
104+
* - Returns undefined if the heap is empty.
105+
*/
106+
remove() {
107+
if (this.data.length > 0) {
108+
const root = this.data[0];
109+
const last = this.data.pop();
110+
if (this.data.length > 0) {
111+
this.data[0] = last;
112+
this.siftDown(0);
113+
}
114+
return root;
115+
} else {
116+
return undefined;
117+
}
118+
}
119+
120+
/**
121+
* Moves the node at the given index down to its proper place in the heap.
122+
* @param index The index of the node to move down.
123+
*/
124+
siftDown(index) {
125+
/** @returns the index containing the smaller value */
126+
const minIndex = (left, right) => {
127+
if (right >= this.data.length) {
128+
if (left >= this.data.length) {
129+
return -1;
130+
} else {
131+
return left;
132+
}
133+
} else {
134+
if (this.compareFn(this.data[left], this.data[right]) <= 0) {
135+
return left;
136+
} else {
137+
return right;
138+
}
139+
}
140+
}
141+
142+
let min = minIndex(this.left(index), this.right(index));
143+
144+
while (
145+
min >= 0
146+
&& this.compareFn(this.data[index], this.data[min]) > 0
147+
) {
148+
[this.data[min], this.data[index]] = [this.data[index], this.data[min]];
149+
index = min;
150+
min = minIndex(this.left(index),
151+
this.right(index));
152+
}
153+
}
154+
155+
/**
156+
* Returns the number of elements in the heap in O(1)
157+
*/
158+
size() {
159+
return this.data.length;
160+
}
161+
162+
/**
163+
* Retrieves but does not remove the root element of this heap in O(1)
164+
* - Returns undefined if the heap is empty.
165+
*/
166+
peek() {
167+
if (this.data.length > 0) {
168+
return this.data[0];
169+
} else {
170+
return undefined;
171+
}
172+
}
173+
}

0 commit comments

Comments
 (0)