Skip to content

Commit c1cf57a

Browse files
committedOct 30, 2020
fix(book/set): split Set chapter into Hash Set and Tree Set for better
coverage

21 files changed

+456
-351
lines changed
 

‎README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ Use Linked Lists when:
271271
#### [HashMaps](book/content/part03/map.asc)
272272

273273
Learn how to implement different types of Maps such as:
274-
- [HashMap](book/content/part03/hashmap.asc)
275-
- [TreeMap](book/content/part03/treemap.asc)
274+
- [HashMap](book/content/part02/hash-map.asc)
275+
- [TreeMap](book/content/part03/tree-map.asc)
276276

277277
Also, [learn the difference between the different Maps implementations](book/content/part03/time-complexity-graph-data-structures.asc):
278278

‎book/B-self-balancing-binary-search-trees.asc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ Let's go one by one.
3636

3737
Right rotation moves a node on the right as a child of another node.
3838

39-
Take a look at the `@example` in the code below.
40-
As you can see we have an unbalanced tree `4-3-2-1`.
39+
Take a look at the examples in the code in the next section.
40+
As you will see we have an unbalanced tree `4-3-2-1`.
4141
We want to balance the tree, for that we need to do a right rotation of node 3.
4242
So, we move node 3 as the right child of the previous child.
4343

@@ -140,4 +140,3 @@ This rotation is also referred to as `RL rotation`.
140140
=== Self-balancing trees implementations
141141

142142
So far, we have study how to make tree rotations which are the basis for self-balancing trees. There are different implementations of self-balancing trees such a Red-Black Tree and AVL Tree.
143-

‎book/D-interview-questions-solutions.asc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ The complexity of any of the BFS methods or DFS is similar.
438438

439439
[#hashmap-q-two-sum]
440440
include::content/part02/hash-map.asc[tag=hashmap-q-two-sum]
441-
// include::content/part03/hashmap.asc[tag=hashmap-q-two-sum]
441+
// include::content/part02/hash-map.asc[tag=hashmap-q-two-sum]
442442

443443
This simple problem can have many solutions; let's explore some.
444444

@@ -482,7 +482,7 @@ include::interview-questions/two-sum.js[tags=description;solution]
482482

483483
[#hashmap-q-subarray-sum-equals-k]
484484
include::content/part02/hash-map.asc[tag=hashmap-q-subarray-sum-equals-k]
485-
// include::content/part03/hashmap.asc[tag=hashmap-q-subarray-sum-equals-k]
485+
// include::content/part02/hash-map.asc[tag=hashmap-q-subarray-sum-equals-k]
486486

487487
This problem has multiple ways to solve it. Let's explore some.
488488

@@ -590,7 +590,7 @@ The sum is 1, however `sum - k` is `0`. If it doesn't exist on the map, we will
590590

591591

592592
[#set-q-most-common-word]
593-
include::content/part03/set.asc[tag=set-q-most-common-word]
593+
include::content/part02/hash-set.asc[tag=set-q-most-common-word]
594594

595595
This problem requires multiple steps. We can use a `Set` for quickly looking up banned words. For getting the count of each word, we used a `Map`.
596596

@@ -632,7 +632,7 @@ include::interview-questions/most-common-word.js[tags=explicit]
632632

633633

634634
[#set-q-longest-substring-without-repeating-characters]
635-
include::content/part03/set.asc[tag=set-q-longest-substring-without-repeating-characters]
635+
include::content/part02/hash-set.asc[tag=set-q-longest-substring-without-repeating-characters]
636636

637637
One of the most efficient ways to find repeating characters is using a `Map` or `Set`. Use a `Map` when you need to keep track of the count/index (e.g., string -> count) and use a `Set` when you only need to know if there are repeated characters or not.
638638

‎book/content/part02/hash-map.asc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ endif::[]
55

66
(((Map))) (((HashMap))) (((HashTable))) (((Data Structures, Linear, HashMap)))
77
[[hashmap-chap]]
8-
=== Hash Map
8+
=== Map
99

1010
A Map is a data structure where a `key` is mapped to a `value`. It's used for a fast lookup of values based on the given key. Only one key can map to a value (no duplicates).
1111

@@ -35,6 +35,7 @@ A Map uses an array internally. It translates the key into an array's index usin
3535

3636
JavaScript has two ways to use Maps: one uses objects (`{}`), and the other is using the built-in `Map`.
3737

38+
[[hashmap-examples]]
3839
.Using Objects as a HashMap.
3940
[source, javascript]
4041
----

‎book/content/part02/hash-set.asc

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
ifndef::imagesdir[]
2+
:imagesdir: ../../images
3+
:codedir: ../../../src
4+
endif::[]
5+
6+
(((Set))) (((Data Structures, Non-Linear, Set)))
7+
[[hash-set-chap]]
8+
=== Set
9+
Set is a data structure that allows you to store unique values. If you try to add the same value, multiple times only one instance will be added. Also, you can check very quickly if a value exists or not. Searching by value on arrays takes `O(n)`. However, searching by value on a Set takes `O(1)` on average.
10+
11+
A Set can be implemented on different ways. One way it's using a <<hashmap-chap, Hash Map>> and other is using a <<tree-map-chap, Tree Map>>. JavaScript has a built-in Hash Set, so that' the one we are going to focus on.
12+
13+
TIP: We will go more in details with <<tree-map-chap, Tree Map>> after we cover the <<binary-search-tree-chap>>.
14+
15+
16+
==== Set vs Array
17+
18+
An array allows you to search a value by index in constant time `O(1)`, however if you don't know the index, searching a value would take you linear time `O(n)`. A Set has doesn't allow you to search value by index, but you can search by value in constant time. The `Set.add` and `Set.has` method both are `O(1)` in average.
19+
20+
Take a look at the following examples:
21+
22+
.Set usage example (using JavaScript built-in Set)
23+
[source, javascript]
24+
----
25+
const set = new Set();
26+
27+
set.add(1); //↪️ Set [ 1 ]
28+
set.add(1); //↪️ Set [ 1 ]
29+
set.add(2); //↪️ Set [ 1, 2 ]
30+
set.add(3); //↪️ Set [ 1, 2, 3 ]
31+
set.has(1); //↪️ true
32+
set.delete(1); //↪️ removes 1 from the set
33+
set.has(1); //↪️ false, 1 has been removed
34+
set.size; //↪️ 2, we just removed one value
35+
console.log(set); //↪️ Set(2) {2, 3}
36+
----
37+
38+
As you can see, even if we insert the same value multiple times, it only gets added once.
39+
40+
Similar to a <<hashmap-examples, map>>, you can also insert objects and any kind of objects. However, be careful, because anything that is not a number, string or symbol would be matched by reference. Let's do some examples.
41+
42+
.Using a Set with objects
43+
[source, javascript]
44+
----
45+
const set = new Set();
46+
47+
set.add({a: 1, b: 2});
48+
set.has({a: 1, b: 2}); // ↪️ false
49+
50+
const a = {a: 1, b: 2};
51+
set.add(a);
52+
set.has(a); // ↪️ true
53+
54+
console.log(set); // Set { [ 1, 2, 3 ], [ 1, 2, 3 ] }
55+
----
56+
57+
As you can see, you can't to find object using a new object (e.g. `{a: 1, b: 2}`), you need the reference to find it.
58+
If you need to match by value, you would need to convert it to an string using `JSON.stringify`.
59+
60+
.Workaround to find objects by value.
61+
[source, javascript]
62+
----
63+
const set = new Set();
64+
65+
set.add(JSON.stringify({a: 1, b: 2}));
66+
67+
set.has(JSON.stringify({a: 1, b: 2})); // ↪️ true
68+
69+
console.log(set); // Set { '{"a":1,"b":2}' }
70+
----
71+
72+
73+
==== Removing duplicates from an array.
74+
75+
One common case for a Set is to eliminate duplicates from an array.
76+
77+
.Removing duplicates from an array
78+
[source, javascript]
79+
----
80+
const arr = [1, 2, 2, 1, 3, 2];
81+
82+
// convert array to set
83+
const set = new Set(arr);
84+
// convert set to array
85+
const uniqueValues = Array.from(set);
86+
// check array
87+
console.log(uniqueValues); // [ 1, 2, 3 ]
88+
----
89+
90+
You can also do it all in one line.
91+
92+
.One-liner to remove duplicates from array.
93+
[source, javascript]
94+
----
95+
const arr = [1, 2, 2, 1, 3, 2];
96+
console.log([...new Set(arr)]); // [ 1, 2, 3 ]
97+
----
98+
99+
==== Time Complexity of a Hash Set
100+
101+
All operation on Hash Set are constant time on average: `O(1)`. Similar to the Hash Map, there are cases when the the Set is getting full and it would do a rehash taking `O(n)` for that one insertion.
102+
103+
// tag::table[]
104+
.Time complexity HashSet
105+
|===
106+
.2+.^s| Data Structure 2+^s| Searching By .2+^.^s| Insert .2+^.^s| Delete .2+^.^s| Space Complexity
107+
^|_Index/Key_ ^|_Value_
108+
| Hash Set ^|O(1) ^|- ^|O(1)* ^|O(1) ^|O(n)
109+
|===
110+
{empty}* = Amortized run time. E.g. rehashing might affect run time to *O(n)*.
111+
// end::table[]
112+
113+
114+
==== Practice Questions
115+
(((Interview Questions, Set)))
116+
117+
// tag::set-q-most-common-word[]
118+
===== Most common word
119+
120+
*ST-1*) _Given a text and a list of banned words.
121+
Find the most common word that is not on the banned list.
122+
You might need to sanitize the text and strip out punctuation `?!,'.`_
123+
// end::set-q-most-common-word[]
124+
125+
// _Seen in interviews at: Amazon._
126+
127+
Examples:
128+
129+
[source, javascript]
130+
----
131+
mostCommonWord(
132+
`How much wood, would a Woodchuck chuck,
133+
if a woodchuck could chuck?`,
134+
['a'],
135+
); // woodchuck or chuck (both show up twice)
136+
137+
mostCommonWord(
138+
`It's a blue ball and its shade... Very BLUE!`,
139+
['and']); // blue (it show up twice, "it" and "its" once)
140+
----
141+
142+
Starter code:
143+
144+
[source, javascript]
145+
----
146+
include::../../interview-questions/most-common-word.js[tags=description;placeholder]
147+
----
148+
149+
150+
_Solution: <<set-q-most-common-word>>_
151+
152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
// tag::set-q-longest-substring-without-repeating-characters[]
163+
===== Longest Without Repeating
164+
165+
*ST-2*) _Find the length of the longest substring without repeating characters._
166+
167+
// end::set-q-longest-substring-without-repeating-characters[]
168+
169+
// _Seen in interviews at: Amazon, Facebook, Bloomberg._
170+
171+
Examples:
172+
173+
[source, javascript]
174+
----
175+
lenLongestSubstring('aaaaa'); // 1 ('a')
176+
lenLongestSubstring('abccdefg'); // 5 ('cdefg')
177+
lenLongestSubstring('abc'); // 3 ('abc')
178+
----
179+
180+
Starter code:
181+
182+
[source, javascript]
183+
----
184+
include::../../interview-questions/longest-substring-without-repeating-characters.js[tags=description;placeholder]
185+
----
186+
187+
188+
_Solution: <<set-q-longest-substring-without-repeating-characters>>_

‎book/content/part03/binary-search-tree.asc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ ifndef::imagesdir[]
33
:codedir: ../../../src
44
endif::[]
55

6-
=== Binary Search Tree
76
(((Binary Search Tree)))
87
(((BST)))
98
(((Data Structures, Non-Linear, Binary Search Tree)))
9+
[[binary-search-tree-chap]]
10+
=== Binary Search Tree
11+
1012

1113
.To recap, the Binary Search Tree (BST) is a tree data structure that keeps the following constraints:
1214
* Each node must have at most two children. Usually referred to as "left" and "right".

‎book/content/part03/graph-search.asc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ graph G {
187187
c0, c1, c2 [color=midnightblue]
188188
// c3 [color=red]
189189
}
190+
191+
a0, b0, c0 [label = 0]
192+
a1, b1, c1 [label = 1]
193+
a2, b2, c2 [label = 2]
194+
b3, c3 [label = 3]
190195
}
191196
....
192197

‎book/content/part03/graph.asc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ include::{codedir}/data-structures/graphs/graph.js[tag=addVertex, indent=0]
200200

201201
If the node doesn't exist, then we create the new node and add it to a `HashMap`.
202202

203-
TIP: <<part03-graph-data-structures#map>> stores key/pair value very efficiently. Lookup is `O(1)`.
203+
TIP: <<tree-map-chap>> stores key/pair value very efficiently. Lookup is `O(1)`.
204204

205205
The `key` is the node's value, while the `value` is the newly created node.
206206

‎book/content/part03/set.asc

Lines changed: 0 additions & 314 deletions
This file was deleted.

‎book/content/part03/time-complexity-graph-data-structures.asc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ In this section, we learned about Graphs applications, properties and how we can
1616
| <<part03-graph-data-structures#bst, BST (unbalanced)>> ^|- ^|O(n) ^|O(n) ^|O(n) ^|O(n)
1717
| <<b-self-balancing-binary-search-trees, BST (balanced)>> ^|- ^|O(log n) ^|O(log n) ^|O(log n) ^|O(n)
1818
| Hash Map (naïve) ^|O(n) ^|O(n) ^|O(n) ^|O(n) ^|O(n)
19-
| <<part03-graph-data-structures#hashmap, HashMap>> (optimized) ^|O(1) ^|O(n) ^|O(1)* ^|O(1) ^|O(n)
20-
| <<part03-graph-data-structures#treemap, TreeMap>> (Red-Black Tree) ^|O(log n) ^|O(n) ^|O(log n) ^|O(log n) ^|O(n)
21-
| <<part03-graph-data-structures#hashset, HashSet>> ^|O(1) ^|- ^|O(1)* ^|O(1) ^|O(n)
22-
| <<part03-graph-data-structures#tree-set, TreeSet>> ^|O(log n) ^|- ^|O(log n) ^|O(log n) ^|O(n)
19+
| <<hashmap-chap, HashMap>> (optimized) ^|O(1) ^|O(n) ^|O(1)* ^|O(1) ^|O(n)
20+
| <<tree-map-chap, TreeMap>> (Red-Black Tree) ^|O(log n) ^|O(n) ^|O(log n) ^|O(log n) ^|O(n)
21+
| <<hash-set-chap, HashSet>> ^|O(1) ^|- ^|O(1)* ^|O(1) ^|O(n)
22+
| <<tree-set-chap, TreeSet>> ^|O(log n) ^|- ^|O(log n) ^|O(log n) ^|O(n)
2323
|===
2424
{empty}* = Amortized run time. E.g. rehashing might affect run time to *O(n)*.
2525
// end::table[]

‎book/content/part03/tree-intro.asc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ image::image32.png[image,width=321,height=193]
6767
Binary trees are one of the most used kinds of trees, and they are used to build other data structures.
6868

6969
.Binary Tree Applications
70-
- <<part03-graph-data-structures#map>>
71-
- <<part03-graph-data-structures#set>>
70+
- <<tree-map-chap>>
71+
- <<tree-set-chap>>
7272
- Priority Queues
7373
- <<part03-graph-data-structures#bst>>
7474

‎book/content/part03/treemap.asc renamed to ‎book/content/part03/tree-map.asc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ ifndef::imagesdir[]
44
endif::[]
55

66
(((TreeMap))) (((Data Structures, Non-Linear, TreeMap))) (((Binary Search Tree))) (((BST)))
7-
[[treemap-chap]]
8-
=== TreeMap
7+
[[tree-map-chap]]
8+
=== Tree Map
99

10-
A Map is an abstract data structure to store pairs of data: *key* and *value*. It also has a fast key lookup of `O(1)` for <<hashmap-chap>> or `O(log n)` for <<treemap-chap>>.
10+
A Map is an abstract data structure to store pairs of data: *key* and *value*. It also has a fast key lookup of `O(1)` for <<hashmap-chap>> or `O(log n)` for <<tree-map-chap>>.
1111

1212
We can implement a Map using two different underlying data structures:
1313

1414
* *HashMap*: it’s a map implementation using an *array* and a *hash function*. The job of the hash function is to convert the `key` into an index that maps to the `value`. Optimized HashMap can have an average runtime of *O(1)*.
1515
* *TreeMap*: it’s a map implementation that uses a self-balanced Binary Search Tree (like <<c-avl-tree>> or Red-Black Tree). The BST nodes store the key, and the value and nodes are sorted by key guaranteeing an *O(log n)* look up.
1616
17-
We already covered <<hashmap-chap>>, so this chapter we are going to focus on TreeMap.
17+
We already covered <<hashmap-chap, Hash Map>>, so this chapter we are going to focus on TreeMap.
18+
19+
TIP: JavaScript only provides (Hash) `Map` that's enough for most needs. But we are going to implement a Tree Map so it's more clear how it works and when it should be used.
1820

1921
A TreeMap is a Map implementation using a Balanced Binary Search Trees.
2022
Implementing a Map with a tree, TreeMap, has a couple of advantages over a HashMap:
@@ -24,7 +26,6 @@ Implementing a Map with a tree, TreeMap, has a couple of advantages over a HashM
2426
* Collisions are not a concern so in the worst case is still *O(log n)*.
2527
* Trees are more space efficient and don’t need to allocate memory beforehand (e.g. `HashMap`’s initial capacity) nor you have to rehash when is getting full.
2628
27-
indexterm:[Runtime, Logarithmic]
2829
Ok, now that you know the advantages, let’s implement it!
2930
For a full comparison read the <<HashMap vs TreeMap>> section.
3031

@@ -103,7 +104,6 @@ The BST implementation does all the heavy lifting.
103104
That’s it! To see the full file in context, click here: https://github.com/amejiarosario/dsa.js/blob/f69b744a1bddd3d99243ca64b3ad46f3f2dd7342/src/data-structures/maps/tree-maps/tree-map.js#L22[here]
104105

105106

106-
<<<
107107
==== HashMap vs TreeMap
108108

109109
.A map can be implemented using hash functions or binary search tree:
@@ -130,7 +130,7 @@ As we discussed so far, there is a trade-off between the implementations.
130130
.2+.^s| Data Structure 2+^s| Searching By .2+^.^s| Insert .2+^.^s| Delete .2+^.^s| Space Complexity
131131
^|_Index/Key_ ^|_Value_
132132
| <<hashmap-chap, Hash Map>> ^|O(1) ^|O(n) ^|O(1)* ^|O(1) ^|O(n)
133-
| <<treemap-chap, Tree Map (Red-Black Tree)>> ^|O(log n) ^|O(n) ^|O(log n) ^|O(log n) ^|O(n)
133+
| <<tree-map-chap, Tree Map (Red-Black Tree)>> ^|O(log n) ^|O(n) ^|O(log n) ^|O(log n) ^|O(n)
134134
|===
135135
{empty}* = Amortized run time. E.g. rehashing might affect run time to *O(n)*.
136136
// end::table[]

‎book/content/part03/tree-set.asc

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
ifndef::imagesdir[]
2+
:imagesdir: ../../images
3+
:codedir: ../../../src
4+
endif::[]
5+
6+
(((TreeSet)))
7+
(((Data Structures, Non-Linear, TreeSet)))
8+
[[tree-set-chap]]
9+
=== Tree Set
10+
11+
A tree set is a data structure that stores unique values and keep them sorted. You can get check if a value exists in `O(log n)` time.
12+
13+
Another way to implement a Set is using a hash function, as we covered on <<hash-set-chap, Hash Set>>. There are some key differences between the two implementations.
14+
15+
==== HashSet vs TreeSet
16+
17+
We can implement a `map` using a *<<b-self-balancing-binary-search-trees, balanced BST>>* or a *<<hashmap-chap,hash function>>*. If we use them to implement a `Set`, we would have a `HashSet` and `TreeSet`. As all data structures there are trade-offs. Here are some key differences:
18+
19+
* `TreeSet`, would return the values sorted in ascending order.
20+
* `HashSet`, would return the values in insertion order.
21+
* Operations on a `HashSet` would take on average O(1), and in the worst case (rehash is due), it would take O(n).
22+
* Operation on a `TreeSet` is always O(log n).
23+
24+
==== Time Complexity Hash Set vs Tree Set
25+
26+
(((Tables, Non-Linear DS, HashSet/TreeSet complexities)))
27+
indexterm:[Runtime, Linear]
28+
(((Logarithmic)))
29+
(((Runtime, Logarithmic)))
30+
31+
// also on: book/content/part03/time-complexity-graph-data-structures.asc
32+
// tag::table[]
33+
.Time complexity HashSet vs TreeSet
34+
|===
35+
.2+.^s| Data Structure 2+^s| Searching By .2+^.^s| Insert .2+^.^s| Delete .2+^.^s| Space Complexity
36+
^|_Index/Key_ ^|_Value_
37+
| <<hash-set-chap, Hash Set>> ^|O(1) ^|- ^|O(1)* ^|O(1) ^|O(n)
38+
| <<tree-set-chap, Tree Set>> ^|O(log n) ^|- ^|O(log n) ^|O(log n) ^|O(n)
39+
|===
40+
{empty}* = Amortized run time. E.g. rehashing might affect run time to *O(n)*.
41+
// end::table[]
42+
43+
44+
TIP: JavaScript only provides (Hash) `Set` that's enough for most needs. But we are going to implement a Tree Set so it's more clear how it works and when it should be used.
45+
46+
==== Implementing a Tree Set
47+
48+
49+
.TreeSet's constructor method and size attribute
50+
[source, javascript]
51+
----
52+
include::{codedir}/data-structures/sets/tree-set.js[tag=constructor]
53+
}
54+
----
55+
<1> Converts an array or any iterable data structure to a set.
56+
57+
An everyday use case for Sets is to remove duplicated values from an array. We can do that bypassing them in the constructor as follows:
58+
59+
.Removing duplicates from an Array using a Set
60+
[source, javascript]
61+
----
62+
set = new TreeSet([1, 2, 3, 2, 1]);
63+
expect(set.size).toBe(3);
64+
expect(Array.from(set.keys())).toEqual([1, 2, 3]);
65+
----
66+
67+
Ok, now let’s implement the add method.
68+
69+
===== Adding elements to a TreeSet
70+
71+
For adding values to the set, we `Tree.add` method.
72+
73+
.TreeSet's constructor method and size attribute
74+
[source, javascript]
75+
----
76+
include::{codedir}/data-structures/sets/tree-set.js[tag=add,indent=0]
77+
----
78+
79+
Our <<Inserting new elements in a BST, BST implementation>> can hold duplicated values. It has a multiplicity tally to keep track of duplicates. However, we don’t dupe in a set. For that, we check if the value is already in the tree.
80+
Don’t worry about adding extra lookups. The
81+
`Tree.has` is also very performant *O(log n)*.
82+
83+
===== Searching for values in a TreeSet
84+
85+
Again, we rely on the Tree implementation to do the heavy lifting:
86+
87+
.TreeSet's `has` method
88+
[source, javascript]
89+
----
90+
include::{codedir}/data-structures/sets/tree-set.js[tag=has, indent=0]
91+
----
92+
93+
===== Deleting elements from a TreeSet
94+
95+
We delete the elements from the TreeSet using the remove method of the BST.
96+
97+
.TreeSet's `delete` method
98+
[source, javascript]
99+
----
100+
include::{codedir}/data-structures/sets/tree-set.js[tag=delete, indent=0]
101+
----
102+
103+
Voilà! That’s it!
104+
105+
===== Converting TreeSet to Array
106+
107+
Another use case for a Set is to convert it to an array or use an iterator (for loops, forEach, …). Let’s provide the method for that:
108+
109+
.TreeSet's iterator
110+
[source, javascript]
111+
----
112+
include::{codedir}/data-structures/sets/tree-set.js[tag=iterator, indent=0]
113+
----
114+
115+
We are using the `inOrderTraversal` method of the BST to go each key in an
116+
ascending order.
117+
118+
.JavaScript Built-in `Symbol` iterator
119+
****
120+
The `Symbol.iterator` built-in symbol specifies the default iterator for
121+
an object. Used by `for...of`, `Array.from` and others.
122+
****
123+
124+
Now we can convert from set to array and vice versa easily. For
125+
instance:
126+
127+
.TreeSet's iterator
128+
[source, javascript]
129+
----
130+
const array = [1, 1, 2, 3, 5];
131+
132+
// array to set
133+
const set = new TreeSet(array);
134+
135+
// set to array
136+
Array.from(set); //↪️ (4) [1, 2, 3, 5]
137+
----
138+
139+
No more duplicates in our array!
140+
141+
Check out our https://github.com/amejiarosario/dsa.js/blob/f69b744a1bddd3d99243ca64b3ad46f3f2dd7342/src/data-structures/sets/tree-set.js#L12[GitHub repo for the full TreeSet implementation].

‎book/content/part04/algorithmic-toolbox.asc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ TIP: TL;DR: Don't start coding right away. First, solve the problem, then write
2323
.. If anything else fails, how would you solve it the dumbest way possible (brute force). We can optimize it later.
2424
. *Test* your algorithm idea with multiple examples
2525
. *Optimize* the solution –Only optimize when you have something working don't try to do both at the same time!
26-
.. Can you trade-off space for speed? Use a <<part03-graph-data-structures#hashmap>> to speed up results!
26+
.. Can you trade-off space for speed? Use a <<hashmap-chap>> to speed up results!
2727
.. Do you have a bunch of recursive and overlapping problems? Try <<Dynamic Programming>>.
2828
.. Re-read requirements and see if you can take advantage of anything. E.g. is the array sorted?
2929
. *Write Code*, yes, now you can code.

‎book/deprecated/old-set.asc

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
ifndef::imagesdir[]
2+
:imagesdir: ../../images
3+
:codedir: ../../../src
4+
endif::[]
5+
6+
[[hashset]]
7+
==== Hash Set Implementation
8+
(((HashSet)))
9+
(((Data Structures, Non-Linear, HashSet)))
10+
The *HashSet* is the set implementation using a HashMap as its underlying data structure.
11+
12+
The HashSet interface will be the same as the built-in `Set` or our previously implemented `TreeSet`.
13+
14+
.HashSet's constructor method and size attribute
15+
[source, javascript]
16+
----
17+
include::{codedir}/data-structures/sets/hash-set.js[tag=constructor]
18+
}
19+
----
20+
21+
This constructor is useful for converting an array to set and initializing the `HashMap`.
22+
23+
===== Inserting values to a HashSet
24+
25+
To insert items in a HashSet, we use the `set` method of the `HashMap`:
26+
27+
.HashSet's `add` method
28+
[source, javascript]
29+
----
30+
include::{codedir}/data-structures/sets/hash-set.js[tag=add, indent=0]
31+
}
32+
----
33+
34+
`HashMap` stores key/value pairs, but we only need the keys for Set, so we ignore the value.
35+
36+
===== Finding values in a HashSet
37+
38+
We use the method `has` to check if a value is on the `Set` or not.
39+
40+
.HashSet's `has` method
41+
[source, javascript]
42+
----
43+
include::{codedir}/data-structures/sets/hash-set.js[tag=has, indent=0]
44+
----
45+
46+
Internally, the `HashMap` will convert the key into an array index using a hash function. If there’s something in the array index bucket, it will return
47+
true, and if it’s empty, it will be false.
48+
49+
===== Deleting values from a HashSet
50+
51+
For deleting a value from a hashSet, we use the HashMap’s delete method:
52+
53+
.HashSet's `delete` method
54+
[source, javascript]
55+
----
56+
include::{codedir}/data-structures/sets/hash-set.js[tag=delete, indent=0]
57+
----
58+
59+
This method has an average runtime of *O(1)*.
60+
61+
==== HashSet vs HashMap Time Complexity
62+
63+
We can say that `HashMap` in on average, more performant O(1) vs. O(log n). However, if a
64+
rehash happens, it will take *O(n)* instead of *O(1)*. A `TreeSet` is always *O(log n)*.
65+
66+
67+
68+
To recap, HashSet and TreeSet will keep data without duplicates. The
69+
difference besides runtime is that:
70+
71+
.TreeSet vs HashSet
72+
* HashSet keeps data in insertion order
73+
* TreeSet keeps data sorted in ascending order.

‎book/part02-linear-data-structures.asc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ When you are aware of the data structures implementations, you spot when to use
1010
.In this part we are going to learn about the following linear data structures:
1111
- <<array-chap>>
1212
- <<hashmap-chap>>
13+
- <<hash-set-chap>>
1314
- <<part02-linear-data-structures#linked-list>>
1415
- <<part02-linear-data-structures#stack>>
1516
- <<part02-linear-data-structures#queue>>
@@ -31,6 +32,9 @@ include::content/part02/array.asc[]
3132
<<<
3233
include::content/part02/hash-map.asc[]
3334

35+
<<<
36+
include::content/part02/hash-set.asc[]
37+
3438
<<<
3539
include::content/part02/linked-list.asc[]
3640

‎book/part03-graph-data-structures.asc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[[part03-graph-data-structures]]
2-
== Graph Data Structures
2+
== Graph & Tree Data Structures
33

44
Graph-based data structures are everywhere whether you realize it or not. You can find them in databases, Web (HTML DOM tree), search algorithms, finding the best route to get home and many more uses. We are going to learn the basic concepts and when to choose one over the other.
55

66
.In this chapter we are going to learn:
77
- Exciting <<part03-graph-data-structures#graph>> data structure applications
88
- Searching efficiently with a <<part03-graph-data-structures#tree>> data structures.
9-
- One of the most versatile data structure of all <<part03-graph-data-structures#hashmap>>.
10-
- Keeping dups out with a <<part03-graph-data-structures#set>>.
9+
- One of the most versatile data structure of all <<hashmap-chap>>.
10+
- Keeping duplicates out with a <<tree-set-chap>>.
1111
By the end of this section, you will know the data structures trade-offs and when to use one over the other.
1212

1313
include::content/part03/tree-intro.asc[]
@@ -24,11 +24,17 @@ include::content/part03/binary-search-tree-traversal.asc[]
2424
// <<<
2525
// include::content/part03/map.asc[]
2626

27-
<<
28-
include::content/part03/treemap.asc[]
27+
// <<<
28+
// include::content/part03/tree-map.asc[]
29+
30+
// <<<
31+
// include::content/part02/hash-set.asc[]
32+
33+
<<<
34+
include::content/part03/tree-map.asc[]
2935

3036
<<<
31-
include::content/part03/set.asc[]
37+
include::content/part03/tree-set.asc[]
3238

3339
<<<
3440
include::content/part03/graph.asc[]

‎src/data-structures/maps/README.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
include::../../../book/content/part03/map.asc[]
22

33
<<<
4-
include::../../../book/content/part03/hashmap.asc[]
4+
include::../../../book/content/part02/hash-map.asc[]
55

66
<<<
7-
include::../../../book/content/part03/treemap.asc[]
7+
include::../../../book/content/part03/tree-map.asc[]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include::../../../../book/content/part03/hashmap.asc[]
1+
include::../../../../book/content/part02/hash-map.asc[]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include::../../../../book/content/part03/treemap.asc[]
1+
include::../../../../book/content/part03/tree-map.asc[]

‎src/data-structures/sets/README.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
include::../../../book/content/part03/set.asc[]
1+
include::../../../book/content/part02/hash-set.asc[]

0 commit comments

Comments
 (0)
Please sign in to comment.