Skip to content

Commit 0ca57d1

Browse files
authored
Merge branch 'master' into master
2 parents 788e272 + 9046d80 commit 0ca57d1

File tree

20 files changed

+785
-7
lines changed

20 files changed

+785
-7
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ be accessed and modified efficiently. More precisely, a data structure is a coll
4949
values, the relationships among them, and the functions or operations that can be applied to
5050
the data.
5151

52+
Remember that each data has its own trade-offs. And you need to pay attention more to why you're choosing a certain data structure than to how to implement it.
53+
5254
`B` - Beginner, `A` - Advanced
5355

5456
* `B` [Linked List](src/data-structures/linked-list)

src/algorithms/search/binary-search/binarySearch.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import Comparator from '../../../utils/comparator/Comparator';
1111

1212
export default function binarySearch(sortedArray, seekElement, comparatorCallback) {
1313
// Let's create comparator from the comparatorCallback function.
14-
// Comparator object will give us common comparison methods like equal() and lessThen().
14+
// Comparator object will give us common comparison methods like equal() and lessThan().
1515
const comparator = new Comparator(comparatorCallback);
1616

1717
// These two indices will contain current array (sub-array) boundaries.

src/algorithms/uncategorized/best-time-to-buy-sell-stocks/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Let's say we have an array of prices `[7, 6, 4, 3, 1]` and we're on the _1st_ da
4646
1. _Option 1: Keep the money_ → profit would equal to the profit from buying/selling the rest of the stocks → `keepProfit = profit([6, 4, 3, 1])`.
4747
2. _Option 2: Buy/sell at current price_ → profit in this case would equal to the profit from buying/selling the rest of the stocks plus (or minus, depending on whether we're selling or buying) the current stock price → `buySellProfit = -7 + profit([6, 4, 3, 1])`.
4848

49-
The overall profit would be equal to → `overalProfit = Max(keepProfit, buySellProfit)`.
49+
The overall profit would be equal to → `overallProfit = Max(keepProfit, buySellProfit)`.
5050

5151
As you can see the `profit([6, 4, 3, 1])` task is being solved in the same recursive manner.
5252

src/algorithms/uncategorized/n-queens/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ and return false.
5959
queen here leads to a solution.
6060
b) If placing queen in [row, column] leads to a solution then return
6161
true.
62-
c) If placing queen doesn't lead to a solution then umark this [row,
62+
c) If placing queen doesn't lead to a solution then unmark this [row,
6363
column] (Backtrack) and go to step (a) to try other rows.
6464
3) If all rows have been tried and nothing worked, return false to trigger
6565
backtracking.

src/data-structures/bloom-filter/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ three factors: the size of the bloom filter, the
9393
number of hash functions we use, and the number
9494
of items that have been inserted into the filter.
9595

96-
The formula to calculate probablity of a false positive is:
96+
The formula to calculate probability of a false positive is:
9797

9898
( 1 - e <sup>-kn/m</sup> ) <sup>k</sup>
9999

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/**
2+
* The minimalistic (ad hoc) version of a DisjointSet (or a UnionFind) data structure
3+
* that doesn't have external dependencies and that is easy to copy-paste and
4+
* use during the coding interview if allowed by the interviewer (since many
5+
* data structures in JS are missing).
6+
*
7+
* Time Complexity:
8+
*
9+
* - Constructor: O(N)
10+
* - Find: O(α(N))
11+
* - Union: O(α(N))
12+
* - Connected: O(α(N))
13+
*
14+
* Where N is the number of vertices in the graph.
15+
* α refers to the Inverse Ackermann function.
16+
* In practice, we assume it's a constant.
17+
* In other words, O(α(N)) is regarded as O(1) on average.
18+
*/
19+
class DisjointSetAdhoc {
20+
/**
21+
* Initializes the set of specified size.
22+
* @param {number} size
23+
*/
24+
constructor(size) {
25+
// The index of a cell is an id of the node in a set.
26+
// The value of a cell is an id (index) of the root node.
27+
// By default, the node is a parent of itself.
28+
this.roots = new Array(size).fill(0).map((_, i) => i);
29+
30+
// Using the heights array to record the height of each node.
31+
// By default each node has a height of 1 because it has no children.
32+
this.heights = new Array(size).fill(1);
33+
}
34+
35+
/**
36+
* Finds the root of node `a`
37+
* @param {number} a
38+
* @returns {number}
39+
*/
40+
find(a) {
41+
if (a === this.roots[a]) return a;
42+
this.roots[a] = this.find(this.roots[a]);
43+
return this.roots[a];
44+
}
45+
46+
/**
47+
* Joins the `a` and `b` nodes into same set.
48+
* @param {number} a
49+
* @param {number} b
50+
* @returns {number}
51+
*/
52+
union(a, b) {
53+
const aRoot = this.find(a);
54+
const bRoot = this.find(b);
55+
56+
if (aRoot === bRoot) return;
57+
58+
if (this.heights[aRoot] > this.heights[bRoot]) {
59+
this.roots[bRoot] = aRoot;
60+
} else if (this.heights[aRoot] < this.heights[bRoot]) {
61+
this.roots[aRoot] = bRoot;
62+
} else {
63+
this.roots[bRoot] = aRoot;
64+
this.heights[aRoot] += 1;
65+
}
66+
}
67+
68+
/**
69+
* Checks if `a` and `b` belong to the same set.
70+
* @param {number} a
71+
* @param {number} b
72+
*/
73+
connected(a, b) {
74+
return this.find(a) === this.find(b);
75+
}
76+
}
77+
78+
export default DisjointSetAdhoc;

src/data-structures/disjoint-set/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ _MakeSet_ creates 8 singletons.
1919

2020
After some operations of _Union_, some sets are grouped together.
2121

22+
## Implementation
23+
24+
- [DisjointSet.js](./DisjointSet.js)
25+
- [DisjointSetAdhoc.js](./DisjointSetAdhoc.js) - The minimalistic (ad hoc) version of a DisjointSet (or a UnionFind) data structure that doesn't have external dependencies and that is easy to copy-paste and use during the coding interview if allowed by the interviewer (since many data structures in JS are missing).
26+
2227
## References
2328

2429
- [Wikipedia](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import DisjointSetAdhoc from '../DisjointSetAdhoc';
2+
3+
describe('DisjointSetAdhoc', () => {
4+
it('should create unions and find connected elements', () => {
5+
const set = new DisjointSetAdhoc(10);
6+
7+
// 1-2-5-6-7 3-8-9 4
8+
set.union(1, 2);
9+
set.union(2, 5);
10+
set.union(5, 6);
11+
set.union(6, 7);
12+
13+
set.union(3, 8);
14+
set.union(8, 9);
15+
16+
expect(set.connected(1, 5)).toBe(true);
17+
expect(set.connected(5, 7)).toBe(true);
18+
expect(set.connected(3, 8)).toBe(true);
19+
20+
expect(set.connected(4, 9)).toBe(false);
21+
expect(set.connected(4, 7)).toBe(false);
22+
23+
// 1-2-5-6-7 3-8-9-4
24+
set.union(9, 4);
25+
26+
expect(set.connected(4, 9)).toBe(true);
27+
expect(set.connected(4, 3)).toBe(true);
28+
expect(set.connected(8, 4)).toBe(true);
29+
30+
expect(set.connected(8, 7)).toBe(false);
31+
expect(set.connected(2, 3)).toBe(false);
32+
});
33+
34+
it('should keep the height of the tree small', () => {
35+
const set = new DisjointSetAdhoc(10);
36+
37+
// 1-2-6-7-9 1 3 4 5
38+
set.union(7, 6);
39+
set.union(1, 2);
40+
set.union(2, 6);
41+
set.union(1, 7);
42+
set.union(9, 1);
43+
44+
expect(set.connected(1, 7)).toBe(true);
45+
expect(set.connected(6, 9)).toBe(true);
46+
expect(set.connected(4, 9)).toBe(false);
47+
48+
expect(Math.max(...set.heights)).toBe(3);
49+
});
50+
});

src/data-structures/heap/Heap.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export default class Heap {
279279
/* istanbul ignore next */
280280
pairIsInCorrectOrder(firstElement, secondElement) {
281281
throw new Error(`
282-
You have to implement heap pair comparision method
282+
You have to implement heap pair comparison method
283283
for ${firstElement} and ${secondElement} values.
284284
`);
285285
}
+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
* The minimalistic (ad hoc) version of a MaxHeap data structure that doesn't have
3+
* external dependencies and that is easy to copy-paste and use during the
4+
* coding interview if allowed by the interviewer (since many data
5+
* structures in JS are missing).
6+
*/
7+
class MaxHeapAdhoc {
8+
constructor(heap = []) {
9+
this.heap = [];
10+
heap.forEach(this.add);
11+
}
12+
13+
add(num) {
14+
this.heap.push(num);
15+
this.heapifyUp();
16+
}
17+
18+
peek() {
19+
return this.heap[0];
20+
}
21+
22+
poll() {
23+
if (this.heap.length === 0) return undefined;
24+
const top = this.heap[0];
25+
this.heap[0] = this.heap[this.heap.length - 1];
26+
this.heap.pop();
27+
this.heapifyDown();
28+
return top;
29+
}
30+
31+
isEmpty() {
32+
return this.heap.length === 0;
33+
}
34+
35+
toString() {
36+
return this.heap.join(',');
37+
}
38+
39+
heapifyUp() {
40+
let nodeIndex = this.heap.length - 1;
41+
while (nodeIndex > 0) {
42+
const parentIndex = this.getParentIndex(nodeIndex);
43+
if (this.heap[parentIndex] >= this.heap[nodeIndex]) break;
44+
this.swap(parentIndex, nodeIndex);
45+
nodeIndex = parentIndex;
46+
}
47+
}
48+
49+
heapifyDown() {
50+
let nodeIndex = 0;
51+
52+
while (
53+
(
54+
this.hasLeftChild(nodeIndex) && this.heap[nodeIndex] < this.leftChild(nodeIndex)
55+
)
56+
|| (
57+
this.hasRightChild(nodeIndex) && this.heap[nodeIndex] < this.rightChild(nodeIndex)
58+
)
59+
) {
60+
const leftIndex = this.getLeftChildIndex(nodeIndex);
61+
const rightIndex = this.getRightChildIndex(nodeIndex);
62+
const left = this.leftChild(nodeIndex);
63+
const right = this.rightChild(nodeIndex);
64+
65+
if (this.hasLeftChild(nodeIndex) && this.hasRightChild(nodeIndex)) {
66+
if (left >= right) {
67+
this.swap(leftIndex, nodeIndex);
68+
nodeIndex = leftIndex;
69+
} else {
70+
this.swap(rightIndex, nodeIndex);
71+
nodeIndex = rightIndex;
72+
}
73+
} else if (this.hasLeftChild(nodeIndex)) {
74+
this.swap(leftIndex, nodeIndex);
75+
nodeIndex = leftIndex;
76+
}
77+
}
78+
}
79+
80+
getLeftChildIndex(parentIndex) {
81+
return (2 * parentIndex) + 1;
82+
}
83+
84+
getRightChildIndex(parentIndex) {
85+
return (2 * parentIndex) + 2;
86+
}
87+
88+
getParentIndex(childIndex) {
89+
return Math.floor((childIndex - 1) / 2);
90+
}
91+
92+
hasLeftChild(parentIndex) {
93+
return this.getLeftChildIndex(parentIndex) < this.heap.length;
94+
}
95+
96+
hasRightChild(parentIndex) {
97+
return this.getRightChildIndex(parentIndex) < this.heap.length;
98+
}
99+
100+
leftChild(parentIndex) {
101+
return this.heap[this.getLeftChildIndex(parentIndex)];
102+
}
103+
104+
rightChild(parentIndex) {
105+
return this.heap[this.getRightChildIndex(parentIndex)];
106+
}
107+
108+
swap(indexOne, indexTwo) {
109+
const tmp = this.heap[indexTwo];
110+
this.heap[indexTwo] = this.heap[indexOne];
111+
this.heap[indexOne] = tmp;
112+
}
113+
}
114+
115+
export default MaxHeapAdhoc;

0 commit comments

Comments
 (0)