Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 802e9d3

Browse files
Merge pull request #75 from amejiarosario/feat/set-questions
feat(book/set): add questions and solutions
2 parents 641b338 + 75aa67a commit 802e9d3

16 files changed

+316
-45
lines changed

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

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -577,35 +577,81 @@ The sum is 1, however `sum - k` is `0`. If it doesn't exist on the map, we will
577577
- Time: `O(n)`. We visit every number once.
578578
- Space: `O(n)`. The map size will be the same as the original array.
579579

580-
// :leveloffset: +1
581580

582-
// === Solutions for TOPIC Questions
583-
// (((Interview Questions Solutions, TOPIC)))
584581

585-
// :leveloffset: -1
582+
:leveloffset: +1
583+
584+
=== Solutions for Set Questions
585+
(((Interview Questions Solutions, Set)))
586+
587+
:leveloffset: -1
588+
589+
590+
[#set-q-most-common-word]
591+
include::content/part03/set.asc[tag=set-q-most-common-word]
592+
593+
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`.
594+
595+
*Algorithm*:
596+
597+
- Convert text to lowercase.
598+
- Remove any special characters `!?',;.`.
599+
- Convert the paragraph into words array.
600+
- Count how many times words occur.
601+
- Exclude banned words from counts.
602+
- Return the word (or first one) that is the most repeated.
603+
604+
*Implementation*:
605+
606+
[source, javascript]
607+
----
608+
include::interview-questions/most-common-word.js[tags=description;solution]
609+
----
610+
611+
Here are heavily relying on Regular Expressions:
612+
613+
- `\W+` would match all non-words.
614+
- `\s+` catches all whitespace.
615+
616+
The line that is mapping words to count seems very busy. Here's another version of the same code a little bit more explicit:
617+
618+
[source, javascript]
619+
----
620+
include::interview-questions/most-common-word.js[tags=explicit]
621+
----
622+
623+
*Complexity Analysis*:
624+
625+
- Time: `O(m + n)`, where `n` is paragraph length and `m` is the number of banned words. If we were NOT using a `Set` for prohibited words, then the runtime would have been `O(mn)`.
626+
- Space: `O(m + n)`. The extra space complexity is given by the size of the `Map` and `Set`.
627+
586628

587-
// [#TOPIC-q-FILENAME]
588-
// include::content/part03/TOPIC_FILE.asc[tag=TOPIC-q-FILENAME]
589629

590-
// RESTATE REQUIREMENTS AND DESCRIPTIONS
591630

592-
// *Algorithm*:
593631

594-
// - STEP 1
595-
// - STEP 2
596-
// - STEP 2.1
597-
// - STEP 2.2
632+
[#set-q-longest-substring-without-repeating-characters]
633+
include::content/part03/set.asc[tag=set-q-longest-substring-without-repeating-characters]
598634

599-
// *Implementation*:
635+
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.
600636

601-
// [source, javascript]
602-
// ----
603-
// include::interview-questions/FILENAME.js[tags=description;solution]
604-
// ----
637+
*Algorithm*:
638+
639+
* Visit each letter.
640+
** Insert the letter on a Set.
641+
** Keep track of the maximum size of the Set in `max`.
642+
** If the letter has been seen before, delete until there's no duplicate.
643+
* Return max.
605644

606-
// IMPLEMENTATION NOTES
645+
*Implementation*:
607646

608-
// *Complexity Analysis*:
647+
[source, javascript]
648+
----
649+
include::interview-questions/longest-substring-without-repeating-characters.js[tags=description;solution]
650+
----
651+
652+
We could also have used a Map and keep track of the indexes, but that's not necessary. In this case, the `Set` is all we need.
653+
654+
*Complexity Analysis*:
609655

610-
// - Time: `O(?)`. WHY?
611-
// - Space: `O(?)`. WHY?
656+
- Time: `O(n)`. We visit each letter once.
657+
- Space: `O(W)`, where `W` is the max length of non-repeating characters. The maximum size of the Set gives the space complexity. In the worst-case scenario, all letters are unique (`W = n`), so our space complexity would be `O(n)`. In the avg. case where there are one or more duplicates, it uses less space than `n`, because `W < n`.

‎book/content/part03/set.asc

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ endif::[]
77
=== Set
88
(((Set)))
99
(((Data Structures, Non-Linear, Set)))
10-
A set is a data structure where duplicated entries are not allowed. Set is like an array with unique values.
10+
A set is a data structure where duplicated entries are not allowed. A Set is like an array with only unique values.
1111

12-
NOTE: JavaScript has already a built-in Set data structure.
12+
NOTE: JavaScript already has a built-in Set data structure.
1313

1414
Take a look at the following
1515
example:
@@ -38,15 +38,15 @@ TIP: A hint... it should perform all operations in *O(1)** or at most *O(log n)*
3838

3939
If we use a `map`, we can accomplish this. However, maps use a key/value pair. If we only use the keys, we can avoid duplicates. Since in a `map` you can only have one key at a time.
4040

41-
As you might remember from the <<part03-graph-data-structures#map>> chapter, there are two ways of implementing a `map` and both can be used to create a `set`. Let's explore the difference between the two implementations are.
41+
As you might remember from the <<part03-graph-data-structures#map>> chapter, there are two ways of implementing a `map`, and both can be used to create a `set`. Let's explore the difference between the two implementations are.
4242

4343
==== HashSet vs TreeSet
4444

45-
We can implement a `map` using a *balanced BST* and using a *hash function*. If we use them to implement a `Set`, then we would have a `HashSet` and `TreeSet` respectively.
45+
We can implement a `map` using a *balanced BST* or a *hash function*. If we use them to implement a `Set`, we would have a `HashSet` and `TreeSet`.
4646

4747
* `TreeSet`, would return the values sorted in ascending order.
4848
* `HashSet`, would return the values in insertion order.
49-
* Operations on a `HashSet` would take on average O(1) and in the worst case (rehash is due), it would take O(n).
49+
* Operations on a `HashSet` would take on average O(1), and in the worst case (rehash is due), it would take O(n).
5050
* Operation on a `TreeSet` is always O(log n).
5151

5252
Let’s implement both!
@@ -65,7 +65,7 @@ include::{codedir}/data-structures/sets/tree-set.js[tag=constructor]
6565
----
6666
<1> Converts an array or any iterable data structure to a set.
6767

68-
A common use case for Sets is to remove duplicated values from an array. We can do that by passing them in the constructor as follows:
68+
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:
6969

7070
.Removing duplicates from an Array using a Set
7171
[source, javascript]
@@ -115,7 +115,7 @@ Voilà! That’s it!
115115

116116
===== Converting TreeSet to Array
117117

118-
A common use case for a Set is to convert it to an array or use in an iterator (for loops, forEach, ...). Let’s provide the method for that:
118+
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:
119119

120120
.TreeSet's iterator
121121
[source, javascript]
@@ -151,7 +151,7 @@ No more duplicates in our array!
151151

152152
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].
153153

154-
Let’s now, implement a `HashSet`.
154+
Let’s now implement a `HashSet`.
155155

156156
[[hashset]]
157157
==== HashSet
@@ -172,7 +172,7 @@ This constructor is useful for converting an array to set and initializing the `
172172

173173
===== Inserting values to a HashSet
174174

175-
To insert items in a HashSet we use the `set` method of the `HashMap`:
175+
To insert items in a HashSet, we use the `set` method of the `HashMap`:
176176

177177
.HashSet's `add` method
178178
[source, javascript]
@@ -181,7 +181,7 @@ include::{codedir}/data-structures/sets/hash-set.js[tag=add, indent=0]
181181
}
182182
----
183183

184-
`HashMap` stores key/value pairs, but for this, we only need the key, and we ignore the value.
184+
`HashMap` stores key/value pairs, but we only need the keys for Set, so we ignore the value.
185185

186186
===== Finding values in a HashSet
187187

@@ -198,7 +198,7 @@ true, and if it’s empty, it will be false.
198198

199199
===== Deleting values from a HashSet
200200

201-
For deleting a value from a hashSet we use the HashMap’s delete method:
201+
For deleting a value from a hashSet, we use the HashMap’s delete method:
202202

203203
.HashSet's `delete` method
204204
[source, javascript]
@@ -210,7 +210,7 @@ This method has an average runtime of *O(1)*.
210210

211211
==== HashSet vs HashMap Time Complexity
212212

213-
We can say that `HashMap` in on average more performant O(1) vs. O(log n). However, if a
213+
We can say that `HashMap` in on average, more performant O(1) vs. O(log n). However, if a
214214
rehash happens, it will take *O(n)* instead of *O(1)*. A `TreeSet` is always *O(log n)*.
215215

216216
(((Tables, Non-Linear DS, HashSet/TreeSet complexities)))
@@ -236,3 +236,80 @@ difference besides runtime is that:
236236
.TreeSet vs HashSet
237237
* HashSet keeps data in insertion order
238238
* TreeSet keeps data sorted in ascending order.
239+
240+
241+
==== Practice Questions
242+
(((Interview Questions, Set)))
243+
244+
// tag::set-q-most-common-word[]
245+
===== Most common word
246+
247+
*ST-1*) _Given a text and a list of banned words.
248+
Find the most common word that is not on the banned list.
249+
You might need to sanitize the text and strip out punctuation `?!,'.`_
250+
// end::set-q-most-common-word[]
251+
252+
// _Seen in interviews at: Amazon._
253+
254+
Examples:
255+
256+
[source, javascript]
257+
----
258+
mostCommonWord(
259+
`How much wood, would a Woodchuck chuck,
260+
if a woodchuck could chuck?`,
261+
['a'],
262+
); // woodchuck or chuck (both show up twice)
263+
264+
mostCommonWord(
265+
`It's a blue ball and its shade... Very BLUE!`,
266+
['and']); // blue (it show up twice, "it" and "its" once)
267+
----
268+
269+
Starter code:
270+
271+
[source, javascript]
272+
----
273+
include::../../interview-questions/most-common-word.js[tags=description;placeholder]
274+
----
275+
276+
277+
_Solution: <<set-q-most-common-word>>_
278+
279+
280+
281+
282+
283+
284+
285+
286+
287+
288+
289+
// tag::set-q-longest-substring-without-repeating-characters[]
290+
===== Longest Without Repeating
291+
292+
*ST-2*) _Find the length of the longest substring without repeating characters._
293+
294+
// end::set-q-longest-substring-without-repeating-characters[]
295+
296+
// _Seen in interviews at: Amazon, Facebook, Bloomberg._
297+
298+
Examples:
299+
300+
[source, javascript]
301+
----
302+
lenLongestSubstring('aaaaa'); // 1 ('a')
303+
lenLongestSubstring('abccdefg'); // 5 ('cdefg')
304+
lenLongestSubstring('abc'); // 3 ('abc')
305+
----
306+
307+
Starter code:
308+
309+
[source, javascript]
310+
----
311+
include::../../interview-questions/longest-substring-without-repeating-characters.js[tags=description;placeholder]
312+
----
313+
314+
315+
_Solution: <<set-q-longest-substring-without-repeating-characters>>_

‎book/interview-questions/binary-tree-right-side-view.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const { Queue } = require('../../src/index');
44
/**
55
* Find the rightmost nodes by level.
66
*
7-
* @example
7+
* @example rightSideView(bt([1,2,3,4])); // [1, 3, 4]
88
* 1 <- 1
99
* / \
1010
* 2 3 <- 3

‎book/interview-questions/buy-sell-stock.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* maxProfit([1, 2, 3]); // => 2
77
* maxProfit([3, 2, 1]); // => 0
88
* @param {number[]} prices - Array with daily stock prices
9+
* @returns {number} - Max profit
910
*/
1011
function maxProfit(prices) {
1112
// end::description[]

‎book/interview-questions/daily-temperatures.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* dailyTemperatures([73, 69, 72, 76, 73]); // [3, 1, 1, 0, 0]
1010
*
1111
* @param {number[]} t - Daily temperatures
12+
* @returns {number[]} - Array with count of days to warmer temp.
1213
*/
1314
function dailyTemperatures(t) {
1415
// end::description[]

‎book/interview-questions/linkedlist-same-data.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
* hasSameData(['he', 'll', 'o'], ['hel', 'lo']); // true
1010
* hasSameData(['hel', 'lo'], ['hi']); // false
1111
*
12-
* @param {ListNode} l1 - The root node of list 1
13-
* @param {ListNode} l2 - The root node of list 2
12+
* @param {ListNode} l1 - The root node of list 1.
13+
* @param {ListNode} l2 - The root node of list 2.
14+
* @returns {boolean} - true if has same data, false otherwise.
1415
*/
1516
function hasSameData(l1, l2) {
1617
// end::description[]
Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
// https://leetcode.com/problems/longest-substring-without-repeating-characters/submissions/
2-
3-
function lengthOfLongestSubstring(s: string): number {
1+
// tag::description[]
2+
/**
3+
* Find the length of the longest substring without duplicates.
4+
* @example lenLongestSubstring('abccxyz'); // => 4 (cxyz)
5+
* @param {string} s - The string.
6+
* @returns {number} - The length of the longest unique substring.
7+
*/
8+
function lenLongestSubstring(s) {
9+
// end::description[]
10+
// tag::placeholder[]
11+
// write your code here...
12+
// end::placeholder[]
13+
// tag::solution[]
414
let max = 0;
515
const set = new Set();
616

@@ -11,4 +21,9 @@ function lengthOfLongestSubstring(s: string): number {
1121
}
1222

1323
return max;
14-
};
24+
// end::solution[]
25+
// tag::description[]
26+
}
27+
// end::description[]
28+
29+
module.exports = { lenLongestSubstring };
Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
1-
describe('',()=>{
2-
it('',()=>{
1+
const{ lenLongestSubstring }=require('./longest-substring-without-repeating-characters');
2+
// const { } = require('../../src/index');
33

4+
[lenLongestSubstring].forEach((fn) => {
5+
describe(`Set: ${fn.name}`, () => {
6+
it('should work with null/empty', () => {
7+
const actual = '';
8+
const expected = 0;
9+
expect(fn(actual)).toEqual(expected);
10+
});
11+
12+
it('should work with small case', () => {
13+
const actual = 'abc';
14+
const expected = 3;
15+
expect(fn(actual)).toEqual(expected);
16+
});
17+
18+
it('should work with other case', () => {
19+
const actual = 'abccdefg';
20+
const expected = 5;
21+
expect(fn(actual)).toEqual(expected);
22+
});
423
});
524
});

‎book/interview-questions/max-subarray.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* maxSubArray([-3,4,-1,2,1,-5]); // => 6
88
*
99
* @param {number[]} a - Array
10+
* @returns {number} - max sum
1011
*/
1112
function maxSubArray(a) {
1213
// end::description[]

‎book/interview-questions/merge-lists.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const ListNode = require('../../src/data-structures/linked-lists/node');
99
*
1010
* @param {ListNode} l1 - The root node of list 1
1111
* @param {ListNode} l2 - The root node of list 2
12+
* @returns {ListNode} - The root of the merged list.
1213
*/
1314
function mergeTwoLists(l1, l2) {
1415
// end::description[]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /