diff --git a/chapter03/3.1 - Three in One/threeInOne.js b/chapter03/3.1 - Three in One/threeInOne.js index 147b6c7..f7917c4 100644 --- a/chapter03/3.1 - Three in One/threeInOne.js +++ b/chapter03/3.1 - Three in One/threeInOne.js @@ -44,12 +44,12 @@ ThreeInOne.prototype.pop2 = function() { return answer; }; -ThreeInOne.prototype.pop3 = function(value) { +ThreeInOne.prototype.pop3 = function() { if (this.isEmpty3()) { return undefined; } - return this.container.pop(value); + return this.container.pop(); }; ThreeInOne.prototype.peek1 = function() { diff --git a/chapter08/8.01 - Triple Step/tripleStepv2.js b/chapter08/8.01 - Triple Step/tripleStepv2.js new file mode 100644 index 0000000..32ae4d8 --- /dev/null +++ b/chapter08/8.01 - Triple Step/tripleStepv2.js @@ -0,0 +1,62 @@ +/* +Recursion and Dynamic Programming (4 steps) +1. start with the recursive backtracking solution (brute force) +2. Optimize by using a memoization table (top-down dynamic programming) +3. Remove the need for recursion (bottom-up dynamic programming) +4. Apply final tricks to reduce the time / memory complexity +*/ + +// Recursive Backtracking +// Time & Space O(n!) +function tripleStep(n) { + if (n < 0) return 0; + if (n === 0) return 1; + return tripleStep(n - 1) + tripleStep(n - 2) + tripleStep(n - 3); +} + +// Top Down Memoization +// Time & Space O(n) +function tripleStep(n, i = 3, memo = [1, 1, 2, 4]) { + if (n < 0) return 0 + if (n < i) return memo[n]; + memo[i] = memo[i - 1] + memo[i - 2] + memo[i - 3]; + return tripleStep(n, i + 1, memo); +} + +// Bottom Up memoization +// Time & Space O(n) +function tripleStep(n, memo = [1, 1, 2, 4]) { + for (let i = 3; i <= n; i++) { + memo[i] = memo[i - 1] + memo[i - 2] + memo[i - 3]; + } + + return memo[memo.length - 1]; +} + +// Constant Space +// Time O(n) & Space O(1) +function tripleStep(n) { + if (n <= 0) return 0; + if (n === 1) return 1; + if (n === 2) return 2; + + let a = 1; + let b = 1; + let c = 2; + + for (let i = 3; i < n; i++) { + let d = a + b + c; + a = b; + b = c; + c = d; + } + return a + b + c; +} + +/* TEST */ +console.log(tripleStep(1), 1); +console.log(tripleStep(2), 2); +console.log(tripleStep(3), 4); +console.log(tripleStep(5), 13); +console.log(tripleStep(7), 44); +console.log(tripleStep(10), 274); diff --git a/chapter10/10.08 - Find Duplicates/findDuplicates.js b/chapter10/10.08 - Find Duplicates/findDuplicates.js index 07bfb1c..1562e64 100644 --- a/chapter10/10.08 - Find Duplicates/findDuplicates.js +++ b/chapter10/10.08 - Find Duplicates/findDuplicates.js @@ -1,2 +1,49 @@ -// sort numbers -// stream through numbers and print elements which is a duplicate of the immediate previous number +// We're given 4 kilobytes (4 * 2^10 * 8 = 32*2^10 bits) of main memory(RAM) to write a program to print all duplicate entries in an array +// from 1 to N where N is at most 32,000 (32*2^10). + +// We can use an Int8Array that uses 1 Byte per element to store 0's if we haven't seen it and 1's if we have seen it. +// The Int8Array typed array represents an array of twos-complement 8-bit signed integers. +// 4 KB > 32,000 bits + +// Time Complexity - O(n) +// Space Complexity - O(n) + +// Let's have a JavaScript Solution of this program: + +function FindDuplicates(arr, range = 32000) { + // Initialize integer 8 bit array with 0's at every index + const numbersSeen = new Int8Array(range); + const duplicates = []; + for (let i = 0; i < arr.length; i++) { + if (numbersSeen[arr[i]] === 0) { + numbersSeen[arr[i]] = 1; + } else { + duplicates.push(arr[i]); + } + } + return duplicates; +} + + const arr = [ + 0, + 1, + 1, + 2, + 4, + 6, + 7, + 9, + 9, + 34, + 56, + 78, + 90, + 101, + 345, + 789, + 999, + 999, + 11000 + ]; + FindDuplicates(arr); +// [1, 9, 999]