Skip to content

Commit c211644

Browse files
Merge pull request #78 from amejiarosario/feat/priority-queue-exercise-2
Feat/priority queue exercise 2
2 parents f248e42 + edf8808 commit c211644

File tree

8 files changed

+233
-51
lines changed

8 files changed

+233
-51
lines changed
+48-19
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,57 @@
1-
// https://leetcode.com/problems/network-delay-time/solution/
2-
function networkDelayTime(times: number[][], N: number, K: number): number {
3-
const graph = new Map<number, [number, number][]>(Array(N).fill(0).map((_, i) => [i + 1, []]));
4-
times.forEach(([u, v, w]) => graph.get(u)?.push([v, w]));
1+
const { PriorityQueue, Queue } = require('../../src/index');
52

6-
const queue = new Queue([[K, 0]]);
7-
const seen = Array(N + 1).fill(Infinity);
3+
// tag::description[]
4+
function networkDelayTime(times, N, K) {
5+
// end::description[]
6+
// tag::placeholder[]
7+
// write your code here...
8+
// end::placeholder[]
9+
// tag::solution[]
10+
const graph = new Map(Array(N).fill(0).map((_, i) => [i + 1, []]));
11+
times.forEach(([u, v, w]) => graph.get(u).push([v, w]));
812

9-
while (queue.size()) {
10-
const [node, dist] = queue.dequeue();
11-
seen[node] = Math.min(seen[node], dist);
13+
const q = new PriorityQueue([[0, K]]);
14+
const dist = new Map();
1215

13-
for (const [adj, w] of graph.get(node) || []) {
14-
if (seen[adj] > dist + w) queue.enqueue([adj, dist + w]);
16+
while (q.size) {
17+
const [d, n] = q.dequeue();
18+
19+
if (dist.has(n)) continue;
20+
dist.set(n, d);
21+
22+
for (const [adj, w] of graph.get(n)) {
23+
if (!dist.has(adj)) q.enqueue([d + w, adj]);
1524
}
1625
}
1726

18-
const max = Math.max(...seen.slice(1));
19-
return max === Infinity ? -1 : max;
20-
};
27+
return dist.size === N ? Math.max(...dist.values()) : -1;
28+
// end::solution[]
29+
// tag::description[]
30+
}
31+
// end::description[]
32+
33+
// tag::networkDelayTimeQueue[]
34+
function networkDelayTimeQueue(times, N, K) {
35+
const graph = new Map(Array(N).fill(0).map((_, i) => [i + 1, []]));
36+
times.forEach(([u, v, w]) => graph.get(u).push([v, w]));
37+
38+
const q = new Queue([[0, K]]);
39+
const dist = new Map();
2140

22-
/*
23-
[[2,1,1],[2,3,1],[3,4,1]]
24-
4
25-
2
41+
while (q.size) {
42+
const [d, n] = q.dequeue();
43+
44+
dist.set(n, dist.has(n) ? Math.min(dist.get(n), d) : d);
45+
46+
for (const [adj, w] of graph.get(n)) {
47+
if (!dist.has(adj) || dist.get(adj) > d + w) {
48+
q.enqueue([d + w, adj]);
49+
}
50+
}
51+
}
2652

53+
return dist.size === N ? Math.max(...dist.values()) : -1;
54+
}
55+
// end::networkDelayTimeQueue[]
2756

28-
*/
57+
module.exports = { networkDelayTime, networkDelayTimeQueue };

book/interview-questions/network-delay-time.spec.js

+45-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/data-structures/heaps/heap.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
class Heap {
99
constructor(comparator = (a, b) => a - b) {
1010
this.array = [];
11-
this.comparator = (i1, i2) => comparator(this.array[i1], this.array[i2]);
11+
this.comparator = (i1, i2) => {
12+
const value = comparator(this.array[i1], this.array[i2]);
13+
if (Number.isNaN(value)) { throw new Error(`Comparator should evaluate to a number. Got ${value} when comparing ${this.array[i1]} with ${this.array[i2]}`); }
14+
return value;
15+
};
1216
}
1317

1418
/**
@@ -34,8 +38,8 @@ class Heap {
3438
* @runtime O(log n)
3539
*/
3640
remove(index = 0) {
37-
if (!this.size()) return null;
38-
this.swap(index, this.size() - 1); // swap with last
41+
if (!this.size) return null;
42+
this.swap(index, this.size - 1); // swap with last
3943
const value = this.array.pop(); // remove element
4044
this.bubbleDown(index);
4145
return value;
@@ -45,7 +49,7 @@ class Heap {
4549
* Returns the number of elements in this collection.
4650
* @runtime O(1)
4751
*/
48-
size() {
52+
get size() {
4953
return this.array.length;
5054
}
5155

@@ -54,7 +58,7 @@ class Heap {
5458
* @runtime O(log n)
5559
*/
5660
bubbleUp() {
57-
let index = this.size() - 1;
61+
let index = this.size - 1;
5862
const parent = (i) => Math.ceil(i / 2 - 1);
5963
while (parent(index) >= 0 && this.comparator(parent(index), index) > 0) {
6064
this.swap(parent(index), index);
@@ -70,18 +74,18 @@ class Heap {
7074
let curr = index;
7175
const left = (i) => 2 * i + 1;
7276
const right = (i) => 2 * i + 2;
73-
const getTopChild = (i) => (right(i) < this.size()
77+
const getTopChild = (i) => (right(i) < this.size
7478
&& this.comparator(left(i), right(i)) > 0 ? right(i) : left(i));
7579

76-
while (left(curr) < this.size() && this.comparator(curr, getTopChild(curr)) > 0) {
80+
while (left(curr) < this.size && this.comparator(curr, getTopChild(curr)) > 0) {
7781
const next = getTopChild(curr);
7882
this.swap(curr, next);
7983
curr = next;
8084
}
8185
}
8286

8387
/**
84-
* "Private": Swap elements on the heap
88+
* Swap elements on the heap
8589
* @runtime O(1)
8690
* @param {number} i1 index 1
8791
* @param {number} i2 index 2

src/data-structures/heaps/heap.spec.js

+21-13
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ const PriorityQueue = require('./priority-queue');
33
const MaxHeap = require('./max-heap');
44
const MinHeap = require('./min-heap');
55

6-
[[Heap], [PriorityQueue], [MinHeap]].forEach(([DS, arg]) => {
7-
describe('Min-Heap (Priority Queue)', () => {
6+
[
7+
[Heap],
8+
[PriorityQueue, [], (a, b) => a - b],
9+
[MinHeap],
10+
].forEach(([DS, ...arg]) => {
11+
describe('Min-Heap and Priority Queue', () => {
812
let heap;
913

1014
beforeEach(() => {
11-
heap = new DS(arg);
15+
heap = new DS(...arg);
1216
});
1317

1418
describe('#contructor', () => {
@@ -21,7 +25,7 @@ const MinHeap = require('./min-heap');
2125
it('should add an element', () => {
2226
expect(heap.add(1)).toBe(undefined);
2327
expect(heap.array).toEqual([1]);
24-
expect(heap.size()).toBe(1);
28+
expect(heap.size).toBe(1);
2529
});
2630

2731
it('should keep things in order', () => {
@@ -31,7 +35,7 @@ const MinHeap = require('./min-heap');
3135
expect(heap.array[0]).toEqual(2);
3236
heap.add(1);
3337
expect(heap.array[0]).toEqual(1);
34-
expect(heap.size()).toEqual(3);
38+
expect(heap.size).toEqual(3);
3539
});
3640
});
3741

@@ -40,7 +44,7 @@ const MinHeap = require('./min-heap');
4044
heap.add(1);
4145
heap.add(0);
4246
expect(heap.remove()).toBe(0);
43-
expect(heap.size()).toBe(1);
47+
expect(heap.size).toBe(1);
4448
expect(heap.array).toEqual([1]);
4549
});
4650

@@ -70,19 +74,23 @@ const MinHeap = require('./min-heap');
7074
expect(heap.remove()).toEqual(1);
7175
expect(heap.remove()).toEqual(2);
7276
expect(heap.remove()).toEqual(3);
73-
expect(heap.size()).toBe(0);
77+
expect(heap.size).toBe(0);
7478
});
7579
});
7680
});
7781
});
7882
});
7983

80-
[[Heap, (a, b) => b - a], [PriorityQueue, (a, b) => b - a], [MaxHeap]].forEach(([DS, arg]) => {
84+
[
85+
[Heap, (a, b) => b - a],
86+
[PriorityQueue, [], (a, b) => b - a],
87+
[MaxHeap],
88+
].forEach(([DS, ...arg]) => {
8189
describe('Max-Heap (Priority Queue)', () => {
8290
let heap;
8391

8492
beforeEach(() => {
85-
heap = new DS(arg);
93+
heap = new DS(...arg);
8694
});
8795

8896
describe('#contructor', () => {
@@ -95,7 +103,7 @@ const MinHeap = require('./min-heap');
95103
it('should add an element', () => {
96104
expect(heap.add(1)).toBe(undefined);
97105
expect(heap.array).toEqual([1]);
98-
expect(heap.size()).toBe(1);
106+
expect(heap.size).toBe(1);
99107
});
100108

101109
it('should keep things in order', () => {
@@ -105,7 +113,7 @@ const MinHeap = require('./min-heap');
105113
expect(heap.array[0]).toEqual(2);
106114
heap.add(3);
107115
expect(heap.array[0]).toEqual(3);
108-
expect(heap.size()).toEqual(3);
116+
expect(heap.size).toEqual(3);
109117
});
110118
});
111119

@@ -114,7 +122,7 @@ const MinHeap = require('./min-heap');
114122
heap.add(1);
115123
heap.add(0);
116124
expect(heap.remove()).toBe(1);
117-
expect(heap.size()).toBe(1);
125+
expect(heap.size).toBe(1);
118126
expect(heap.array).toEqual([0]);
119127
});
120128

@@ -156,7 +164,7 @@ const MinHeap = require('./min-heap');
156164
expect(heap.remove()).toEqual(2);
157165
expect(heap.remove()).toEqual(1);
158166
expect(heap.remove()).toEqual(0);
159-
expect(heap.size()).toBe(0);
167+
expect(heap.size).toBe(0);
160168
});
161169
});
162170
});

src/data-structures/heaps/median-heap.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class MedianHeap {
3030
}
3131

3232
// rebalance if the sizes of the heaps differ by more than one element
33-
if (Math.abs(this.min.size() - this.max.size()) > 1) {
33+
if (Math.abs(this.min.size - this.max.size) > 1) {
3434
// extract the min/max from the heap with more elements and insert it into the other heap.
35-
if (this.min.size() > this.max.size()) {
35+
if (this.min.size > this.max.size) {
3636
this.max.add(this.min.remove());
3737
} else {
3838
this.min.add(this.max.remove());
@@ -47,12 +47,12 @@ class MedianHeap {
4747
findMedian() {
4848
let median;
4949

50-
if (this.max.size() === this.min.size()) {
50+
if (this.max.size === this.min.size) {
5151
// When both heaps contain the same number of elements,
5252
// the total number of elements is even.
5353
// The median is the mean of the two middle elements.
5454
median = (this.max.peek() + this.min.peek()) / 2;
55-
} else if (this.max.size() > this.min.size()) {
55+
} else if (this.max.size > this.min.size) {
5656
// when the max-heap contains one more element than the min-heap,
5757
// the median is in the top of the max-heap.
5858
median = this.max.peek();
@@ -67,8 +67,8 @@ class MedianHeap {
6767
/**
6868
* Return size of the heap.
6969
*/
70-
size() {
71-
return this.min.size() + this.max.size();
70+
get size() {
71+
return this.min.size + this.max.size;
7272
}
7373
}
7474

src/data-structures/heaps/median-heap.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ describe('Median Heap', () => {
1010
describe('#add', () => {
1111
it('should work', () => {
1212
expect(medianHeap.add(1)).toEqual(undefined);
13-
expect(medianHeap.size()).toEqual(1);
13+
expect(medianHeap.size).toEqual(1);
1414
});
1515

1616
it('should work', () => {
1717
expect(medianHeap.add(1)).toEqual(undefined);
1818
expect(medianHeap.add(1)).toEqual(undefined);
19-
expect(medianHeap.size()).toEqual(2);
19+
expect(medianHeap.size).toEqual(2);
2020
});
2121
});
2222

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
11
const Heap = require('./heap');
22

3-
class PriorityQueue extends Heap { }
3+
class PriorityQueue extends Heap {
4+
constructor(iterable = [], comparator = (a, b) => a[0] - b[0]) {
5+
super(comparator);
6+
Array.from(iterable).forEach((el) => this.add(el));
7+
}
8+
9+
/**
10+
* Add data to the Queue with Priority
11+
* @param {[number, any]|any} value - Pair with [priority, value]
12+
* any object as value is also possible if a custom comparator is passed in.
13+
* @returns {void}
14+
*/
15+
enqueue(value) {
16+
super.add(value);
17+
}
18+
19+
/**
20+
* Remove from the queue the element with the highest priority.
21+
* @returns {[number, any]|any}
22+
*/
23+
dequeue() {
24+
return super.remove();
25+
}
26+
}
427

528
module.exports = PriorityQueue;

0 commit comments

Comments
 (0)