From f04e7a446c24133c72e666aa2857f36df230b736 Mon Sep 17 00:00:00 2001 From: bialesdaniel Date: Wed, 10 Oct 2018 05:00:21 -0400 Subject: [PATCH 01/24] 2.5 - add recursion solution and bonus problem (#30) * adding an example that is slightly less performant but easier to read. * adding an even better recursion solution * creating recursive examples of exercise 2.5 and the added the forward solution * made some formatting changes for the recursions algorithm --- .../2.5 - Sum Lists/sumLists - forward.js | 83 +++++++++++++++++++ .../2.5 - Sum Lists/sumLists - recursion.js | 36 ++++++++ 2 files changed, 119 insertions(+) create mode 100644 chapter02/2.5 - Sum Lists/sumLists - forward.js create mode 100644 chapter02/2.5 - Sum Lists/sumLists - recursion.js diff --git a/chapter02/2.5 - Sum Lists/sumLists - forward.js b/chapter02/2.5 - Sum Lists/sumLists - forward.js new file mode 100644 index 0000000..bbb7dd3 --- /dev/null +++ b/chapter02/2.5 - Sum Lists/sumLists - forward.js @@ -0,0 +1,83 @@ +const LinkedList = require('./../util/LinkedList') +const printList = require('./../util/printList') + +function sumLinkedListsForward(list1, list2) { + if (!list1 && !list2) { + return null + } + let length1 = length(list1) + let length2 = length(list2) + + if (length1 > length2) { + list2 = padList(list2, length1 - length2) + } else if (length1 < length2) { + list1 = padList(list1, length2 - length1) + } + + const { head, nextDigitValue } = carryBase10(sumAndAppendNodes(list1, list2), 0) + return nextDigitValue ? appendToStart(head, new LinkedList(nextDigitValue)) : head +} + +function length(node) { + let count = 0 + while (node) { + count++ + node = node.next + } + return count +} + +function padList(shortList, padding) { + while (padding > 0) { + shortList = appendToStart(shortList, new LinkedList(0)) + padding-- + } + return shortList +} + +function appendToStart(head, node) { + node.next = head + return node +} + +function sumAndAppendNodes(node1, node2) { + let value = (node1 ? node1.value : 0) + (node2 ? node2.value : 0) + if (!node1.next && !node2.next) { + return new LinkedList(value) + } + const { + head, + nextDigitValue + } = carryBase10(sumAndAppendNodes(node1.next, node2.next), value) + return appendToStart(head, new LinkedList(nextDigitValue)) +} + +function carryBase10(head, nextDigitValue) { + if (head.value >= 10) { + head.value = head.value % 10 + nextDigitValue += 1 + } + return { + head, + nextDigitValue + } +} + +// Input: (6 -> 1 -> 7) + (2 -> 9 -> 5). this case refers to 617 + 295 +// Output: 9 -> 1 -> 2. the answer refers to 912 + +var a = new LinkedList(6) +var b = new LinkedList(1) +var c = new LinkedList(7) + +a.next = b +b.next = c + +var d = new LinkedList(2) +var e = new LinkedList(9) +var f = new LinkedList(5) + +d.next = e +e.next = f + +printList(sumLinkedListsForward(a, d)) diff --git a/chapter02/2.5 - Sum Lists/sumLists - recursion.js b/chapter02/2.5 - Sum Lists/sumLists - recursion.js new file mode 100644 index 0000000..2289263 --- /dev/null +++ b/chapter02/2.5 - Sum Lists/sumLists - recursion.js @@ -0,0 +1,36 @@ +const LinkedList = require('./../util/LinkedList') +const printList = require('./../util/printList') + +function sumLinkedLists(node1, node2, carry=0){ + if(!node1 && !node2 && carry===0){ + return null + } + let value = carry + value += node1 ? node1.value : 0 + value += node2 ? node2.value : 0 + const node = new LinkedList(value%10) + node.next = sumLinkedLists( + node1 ? node1.next : null, + node2 ? node2.next : null, + value > 10 ? 1 : 0) + return node +} + +// Input: (7 -> 1 -> 6) + (5 -> 9 -> 2). this case refers to 617 + 295 +// Output: 2 -> 1 -> 9. the answer refers to 912 + +var a = new LinkedList(7) +var b = new LinkedList(1) +var c = new LinkedList(6) + +a.next = b +b.next = c + +var d = new LinkedList(5) +var e = new LinkedList(9) +var f = new LinkedList(2) + +d.next = e +e.next = f + +printList(sumLinkedLists(a,d)) From afc0084acf9083969ca06ab28d54b29c17582105 Mon Sep 17 00:00:00 2001 From: Pedro Ivan Lopez Date: Mon, 5 Aug 2019 12:33:18 -0500 Subject: [PATCH 02/24] feat: 1.1 solution with bit array/vector & ES6 (#44) --- chapter01/1.1 - Is Unique/isUnique.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/chapter01/1.1 - Is Unique/isUnique.js b/chapter01/1.1 - Is Unique/isUnique.js index 136496c..002644e 100644 --- a/chapter01/1.1 - Is Unique/isUnique.js +++ b/chapter01/1.1 - Is Unique/isUnique.js @@ -12,5 +12,19 @@ var allUniqueChars = function(string) { return true; // if no match, return true }; +const everyCharUnique = (str, indexOffset = 'a'.charCodeAt()) => { + let counterTable = Number(); + for(let index of [...str].map(c => c.charCodeAt() - indexOffset)) { + const mask = 1 << index; + if(counterTable & mask) + return false; + counterTable |= mask; + } + return true; +}; + /* TESTS */ -// log some tests here \ No newline at end of file +console.log(everyCharUnique('abcd'), 'true'); +console.log(everyCharUnique('abccd'), 'false'); +console.log(everyCharUnique('bhjjb'), 'false'); +console.log(everyCharUnique('mdjq'), 'true'); From 4cf9bebdc1e7c9242c52d3d5798dfe7153a87232 Mon Sep 17 00:00:00 2001 From: Sai Charan R Patlolla Date: Sat, 24 Aug 2019 14:26:55 -0400 Subject: [PATCH 03/24] feat(q1.3): another implementation for urlify (#51) * Created a new file urlify-2 with better solution * Addressed the remarks --- chapter01/1.3 - URLify/urlify-2.js | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 chapter01/1.3 - URLify/urlify-2.js diff --git a/chapter01/1.3 - URLify/urlify-2.js b/chapter01/1.3 - URLify/urlify-2.js new file mode 100644 index 0000000..be53567 --- /dev/null +++ b/chapter01/1.3 - URLify/urlify-2.js @@ -0,0 +1,11 @@ +const replaceUrlSpaces = (str) => { + const convertToArray = str.trim().split(''); + for(let i in convertToArray) { + if(convertToArray[i] === " ") { + convertToArray[i] = "%20" + } + } + return convertToArray.join(''); +} + + console.log(replaceUrlSpaces("Sai Charan P")); From 0605eff67986aa687eb6a68baca66e6dec75c120 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2019 01:54:28 -0800 Subject: [PATCH 04/24] chore: bump eslint from 3.19.0 to 6.6.0 (#52) Bumps [eslint](https://github.com/eslint/eslint) from 3.19.0 to 6.6.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v3.19.0...v6.6.0) Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 975ebe9..aaa9743 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "dependencies": {}, "devDependencies": { - "eslint": "^3.14.1" + "eslint": "^6.6.0" }, "license": "MIT" } From dfc835599da4f86d0811ee3cfcaa0b6a39d75a18 Mon Sep 17 00:00:00 2001 From: Vivek Chandra Date: Sun, 5 Jan 2020 17:23:39 +0000 Subject: [PATCH 05/24] fix: update code results (#53) --- chapter02/2.4 - Partition/partition.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapter02/2.4 - Partition/partition.js b/chapter02/2.4 - Partition/partition.js index 841f687..5e69440 100644 --- a/chapter02/2.4 - Partition/partition.js +++ b/chapter02/2.4 - Partition/partition.js @@ -40,7 +40,7 @@ var partition = function(head, partition) { /* TESTS */ // Input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 [partition = 5] -// Output: 3 -> 1 -> 2 -> 10 -> 5 -> 5 -> 8 +// Output: 3 -> 2 -> 1 -> 5 -> 8 -> 5 -> 10 var printList = function(a) { while (a !== null) { From 4b10530c1350a9c1260107eb8bf3c77f524e9f3b Mon Sep 17 00:00:00 2001 From: Vivek Chandra Date: Tue, 7 Jan 2020 16:42:30 +0000 Subject: [PATCH 06/24] fix(2.4): give result as per the question (#54) * Patch - 1 * Updating the code to rectify the result to show the correct order of expected result * Updating the results w.r.t code changes --- chapter02/2.4 - Partition/partition.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/chapter02/2.4 - Partition/partition.js b/chapter02/2.4 - Partition/partition.js index 5e69440..6253911 100644 --- a/chapter02/2.4 - Partition/partition.js +++ b/chapter02/2.4 - Partition/partition.js @@ -8,8 +8,10 @@ var partition = function(head, partition) { // and attach nodes with values less than partition value to the left // and nodes with vallues more than partition value to the right var left; + var middle; var right; var currLeft = null; + var currMiddle = null; var currRight = null; var node = head; @@ -22,6 +24,14 @@ var partition = function(head, partition) { currLeft.next = node; currLeft = currLeft.next; } + } else if (node.value === partition) { + if (currMiddle === null) { + middle = node; + currMiddle = middle; + } else { + currMiddle.next = node; + currMiddle = currMiddle.next; + } } else { if (currRight === null) { right = node; @@ -34,13 +44,16 @@ var partition = function(head, partition) { node = node.next; } currRight.next = null; - currLeft.next = right; // connect two partitions together + // connect the left values with those matching the partition value + currLeft.next = middle; + // connect the middle with the right partitions + currMiddle.next = right; return left; // return head of new linkedList }; /* TESTS */ // Input: 3 -> 5 -> 8 -> 5 -> 10 -> 2 -> 1 [partition = 5] -// Output: 3 -> 2 -> 1 -> 5 -> 8 -> 5 -> 10 +// Output: 3 -> 2 -> 1 -> 5 -> 5 -> 8 -> 10 var printList = function(a) { while (a !== null) { From 685adc538528183e434c6c84fcebc910ab893eff Mon Sep 17 00:00:00 2001 From: Varun Mara Date: Mon, 17 Feb 2020 13:17:40 -0600 Subject: [PATCH 07/24] feat: solved URLify with O(n) time complexity (#56) --- chapter01/1.3 - URLify/urlify-3.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 chapter01/1.3 - URLify/urlify-3.js diff --git a/chapter01/1.3 - URLify/urlify-3.js b/chapter01/1.3 - URLify/urlify-3.js new file mode 100644 index 0000000..3add8f9 --- /dev/null +++ b/chapter01/1.3 - URLify/urlify-3.js @@ -0,0 +1,20 @@ +function urlify(str, len) { + let s = ""; + let totalSpaces = str.length - len; + let frontSpaces = 0; + let flag = false; + for (let i = 0; i < str.length; i++) { + if (flag === false) { + if (str[i] === " ") frontSpaces++; + else flag = true; + } + if (flag === true && i < str.length - (totalSpaces - frontSpaces)) { + if (str[i] === " ") s += "%20"; + else s += str[i]; + } + } + + return s; +} + +console.log(urlify("Mr John Smith ", 13)); From 1cc1f8b0fe293f62157d43cb4eff32d9e9610600 Mon Sep 17 00:00:00 2001 From: Chris Milson Date: Thu, 19 Mar 2020 19:56:06 +0900 Subject: [PATCH 08/24] Update implementation to match question (#59) The original implementation did not answer the question in the book. closes #58 --- .../2.8 - Loop Detection/loopDetection.js | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/chapter02/2.8 - Loop Detection/loopDetection.js b/chapter02/2.8 - Loop Detection/loopDetection.js index c444194..4026c02 100644 --- a/chapter02/2.8 - Loop Detection/loopDetection.js +++ b/chapter02/2.8 - Loop Detection/loopDetection.js @@ -1,22 +1,27 @@ var LinkedList = require('./../util/LinkedList'); var loopDetection = (head) => { - var hare = head; - var tortoise = head; - while (hare !== null) { - tortoise = tortoise.next; - hare = hare.next; - if (hare === tortoise && hare !== head.next) { - return true; - } - if (hare !== null) { - hare = hare.next; - if (hare === tortoise) { - return true; - } - } + // The null checking code will handle lists with no loops. + if (!head || !head.next) return null + + var hare = head + var tortoise = head + + do { + hare = hare.next + tortoise = tortoise.next + if (!hare || !hare.next) return null + hare = hare.next + } while (hare !== tortoise) + + tortoise = head + + while (hare !== tortoise) { + hare = hare.next + tortoise = tortoise.next } - return false; + + return hare }; /* TEST */ @@ -36,7 +41,7 @@ d.next = e; e.next = f; f.next = c; -console.log(loopDetection(a), true); +console.log(loopDetection(a) === c, true); var A = new LinkedList(); var B = new LinkedList(); @@ -51,4 +56,4 @@ C.next = D; D.next = E; E.next = F; -console.log(loopDetection(A), false); +console.log(loopDetection(A) === null, false); From fbf50ff6288a52f87a81625462b7829a957cadd0 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Sat, 28 Mar 2020 11:25:32 +0300 Subject: [PATCH 09/24] fix(chap.2): redo 2.1 solution with new linkedlist class (#60) * chore: rewrite queue to es6 * fix(2.1): redo with proper linked list redid 2.1 using a properly defined linked list --- chapter02/2.1 - Remove Dups/removeDups.js | 106 +++++++--------------- chapter02/util/LinkedListX.js | 95 +++++++++++++++++++ chapter04/util/Queue.js | 72 +++++++++------ 3 files changed, 168 insertions(+), 105 deletions(-) create mode 100644 chapter02/util/LinkedListX.js diff --git a/chapter02/2.1 - Remove Dups/removeDups.js b/chapter02/2.1 - Remove Dups/removeDups.js index 1a34d5b..c424136 100644 --- a/chapter02/2.1 - Remove Dups/removeDups.js +++ b/chapter02/2.1 - Remove Dups/removeDups.js @@ -1,82 +1,38 @@ -/* CLASS */ -var LinkedList = function(value) { - this.value = value; - this.next = null; -}; - -/* FUNCTIONS */ -var checkDups = function(head, node) { - var currNode = head; - while (currNode !== node) { - if (currNode.value === node.value) { - return true; +// remiveDups redone +const LinkedList = require("../util/LinkedListX"); + +function removeDuplicates(list) { + const _set = new Set(); + let cur = list.head; + let prev = null; + while (cur) { + if (_set.has(cur.value)) { + // duplicate found + // de-link it from the list + // cur jumps next but previous stays + // right behind cur (as always) + let elem = cur; + prev.next = cur.next; + cur = cur.next; + elem.next = null; } - currNode = currNode.next; - } - return false; -}; - -var printLinkedList = function(head) { - var node = head; - console.log('start of linked list'); - while (node !== null) { - console.log(node.value); - node = node.next; - } - console.log('end of linked list'); -}; - -var removeDups = function(head) { - var node = head; - while (node !== null) { - if (node.next !== null && checkDups(head, node.next)) { - node.next = node.next.next; - } else { - node = node.next; + else { + // add to the set + _set.add(cur.value); + prev = cur; + cur = cur.next; } } - return head; -}; - -/* TESTS */ -var a = new LinkedList('a'); -var b = new LinkedList('b'); -var c = new LinkedList('c'); -var d = new LinkedList('d'); -var e = new LinkedList('e'); - -a.next = b; -b.next = c; -c.next = d; -d.next = e; - -removeDups(a); -printLinkedList(a); - -var f = new LinkedList('f'); -var g = new LinkedList('g'); -var h = new LinkedList('g'); -var i = new LinkedList('g'); -var j = new LinkedList('g'); - -f.next = g; -g.next = h; -h.next = i; -i.next = j; -removeDups(f); -printLinkedList(f); + return list; +} -var k = new LinkedList('g'); -var l = new LinkedList('g'); -var m = new LinkedList('g'); -var n = new LinkedList('b'); -var o = new LinkedList('g'); +// quick test +let list = new LinkedList(); +for (let elem of [1, 5, 1, 6, 8, 6, 8, 8, 8, 8]) { + list.append(elem); +} -k.next = l; -l.next = m; -m.next = n; -n.next = o; +removeDuplicates(list); -removeDups(k); -printLinkedList(k); +console.log(list._toArray()); // [1, 5, 6, 8] diff --git a/chapter02/util/LinkedListX.js b/chapter02/util/LinkedListX.js new file mode 100644 index 0000000..2b70a5d --- /dev/null +++ b/chapter02/util/LinkedListX.js @@ -0,0 +1,95 @@ +// a new implementation of the linked list +/* +ADT: +# Main operations +prepend(value) -> Add a node in the beginning +append(value) -> Add a node in the end +pop() -> Remove a node from the end +popFirst() -> Remove a node from the beginning +head() -> Return the first node +tail() -> Return the last node +remove(Node)* -> Remove Node from the list +*/ + +// NOTE: no type-safety + +class Node { + constructor(value) { + this.value = value + this.next = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + } + return first; + } + + head() { + return this.head; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } +} + +module.exports = LinkedList; diff --git a/chapter04/util/Queue.js b/chapter04/util/Queue.js index 55b8c4d..f68802a 100644 --- a/chapter04/util/Queue.js +++ b/chapter04/util/Queue.js @@ -1,41 +1,53 @@ // implement a queue using linkedLists -var LinkedList = require('./LinkedList'); - -var Queue = function() { - this.front = null; - this.back = null; -}; - -Queue.prototype.add = function(value) { - var node = new LinkedList(value); - if (this.front === null) { - this.front = node; - this.back = node; - } else { - var prevBack = this.back; - this.back = node; - prevBack.next = this.back; +class LinkedListNode { + constructor(value) { + this.value = value; + this.next = null; } -}; +} -Queue.prototype.remove = function() { - var removed = this.front; - if (this.front === this.back) { +class Queue { + constructor() { this.front = null; this.back = null; - } else { - this.front = this.front.next; } - return removed !== null ? removed.value : null; -}; -Queue.prototype.peek = function() { - return this.front !== null ? this.front.value : null; -}; + enqueue(value) { + const node = new LinkedListNode(value); + if (this.front === null) { + this.front = node; + this.back = node; + } else { + var prevBack = this.back; + this.back = node; + prevBack.next = this.back; + } + } + + dequeue() { + const removed = this.front; + if (this.front === this.back) { + this.front = null; + this.back = null; + } else { + this.front = this.front.next; + } + return removed !== null ? removed.value : null; + } + + peek() { + return this.front !== null ? this.front.value : null; + } + + isEmpty() { + return this.front === null; + } +} + +// alias +Queue.prototype.add = Queue.prototype.enqueue; +Queue.prototype.remove = Queue.prototype.dequeue; -Queue.prototype.isEmpty = function() { - return this.front === null; -}; module.exports = Queue; From 79a888673b1fb2a0fdc71b8f58dcc3196dfc45ea Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Sat, 28 Mar 2020 15:26:58 +0300 Subject: [PATCH 10/24] fix: redo linkedlists, stacks and queues (#61) This commit fixes the implementations for stacks, linked lists (singly) and queues, across Chapter 2, 3, 4 and 7. Maintains the previous interface for b/c. --- chapter02/util/LinkedListX.js | 2 + chapter03/util/LinkedList.js | 88 +++++++++++++++++++++++++++++++++-- chapter03/util/Queue.js | 59 +++++++++++------------ chapter03/util/Stack.js | 61 +++++++++++++----------- chapter04/util/LinkedList.js | 88 +++++++++++++++++++++++++++++++++-- chapter04/util/Queue.js | 41 ++++++---------- chapter04/util/Stack.js | 61 +++++++++++++----------- chapter07/util/LinkedList.js | 88 +++++++++++++++++++++++++++++++++-- chapter07/util/Queue.js | 59 +++++++++++------------ chapter07/util/Stack.js | 61 +++++++++++++----------- 10 files changed, 425 insertions(+), 183 deletions(-) diff --git a/chapter02/util/LinkedListX.js b/chapter02/util/LinkedListX.js index 2b70a5d..2bd8fdc 100644 --- a/chapter02/util/LinkedListX.js +++ b/chapter02/util/LinkedListX.js @@ -68,7 +68,9 @@ class LinkedList { let first = this.head; if (this.head && this.head.next) { this.head = this.head.next; + first.next = null; } + else this.head = null; return first; } diff --git a/chapter03/util/LinkedList.js b/chapter03/util/LinkedList.js index 6164dbc..ba21422 100644 --- a/chapter03/util/LinkedList.js +++ b/chapter03/util/LinkedList.js @@ -1,6 +1,84 @@ -var LinkedList = function(value) { - this.value = value; - this.next = null; -}; +// moved from chapter 2 (/util/LinkedListX.js) -module.exports = LinkedList; \ No newline at end of file +class Node { + constructor(value) { + this.value = value + this.next = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + first.next = null; + } + else this.head = null; + return first; + } + + head() { + return this.head; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } +} + +module.exports = LinkedList; diff --git a/chapter03/util/Queue.js b/chapter03/util/Queue.js index 55b8c4d..1eeab01 100644 --- a/chapter03/util/Queue.js +++ b/chapter03/util/Queue.js @@ -1,41 +1,36 @@ // implement a queue using linkedLists var LinkedList = require('./LinkedList'); -var Queue = function() { - this.front = null; - this.back = null; -}; - -Queue.prototype.add = function(value) { - var node = new LinkedList(value); - if (this.front === null) { - this.front = node; - this.back = node; - } else { - var prevBack = this.back; - this.back = node; - prevBack.next = this.back; +class Queue { + constructor() { + this._list = new LinkedList(); } -}; - -Queue.prototype.remove = function() { - var removed = this.front; - if (this.front === this.back) { - this.front = null; - this.back = null; - } else { - this.front = this.front.next; + + enqueue(value) { + this._list.append(value); + } + + dequeue() { + let node = this._list.popFirst(); + return node.value; + } + + peek() { + return this._list.head ? this._list.head.value : null; + } + + isEmpty() { + return this._list.head == null; } - return removed !== null ? removed.value : null; -}; -Queue.prototype.peek = function() { - return this.front !== null ? this.front.value : null; -}; + _toArray() { + return this._list._toArray(); + } +} -Queue.prototype.isEmpty = function() { - return this.front === null; -}; +// alias +Queue.prototype.add = Queue.prototype.enqueue; +Queue.prototype.remove = Queue.prototype.dequeue; module.exports = Queue; @@ -44,8 +39,10 @@ module.exports = Queue; // q.add('a'); // q.add('b'); // q.add('c'); +// console.log(q._toArray()); // console.log(q.remove(), 'a'); // console.log(q.peek(), 'b'); // console.log(q.remove(), 'b'); // console.log(q.remove(), 'c'); // console.log(q.isEmpty(), true); +// console.log(q._toArray()); diff --git a/chapter03/util/Stack.js b/chapter03/util/Stack.js index 99cc0ea..a04e649 100644 --- a/chapter03/util/Stack.js +++ b/chapter03/util/Stack.js @@ -1,31 +1,40 @@ -// implement a stack using linkedLists -var LinkedList = require('./LinkedList'); - -var Stack = function() { - this.top = null; -}; - -Stack.prototype.push = function(value) { - var node = new LinkedList(value); - node.next = this.top; - this.top = node; -}; - -Stack.prototype.pop = function() { - var popped = this.top; - if (this.top !== null) { - this.top = this.top.next; +// simple implementation of a stack +// using an Array + +/* +Interface: +- push(value) +- pop() +- peek() +- isEmpty() +- size() +*/ +class Stack { + constructor() { + this._data = []; } - return popped.value; -}; -Stack.prototype.peek = function() { - return this.top !== null ? this.top.value : null; -}; + size() { + return this._data.length; + } + + isEmpty() { + return this.size() == 0; + } + + push(value) { + this._data.push(value); + } + + pop() { + return this._data.pop(); + } -Stack.prototype.isEmpty = function() { - return this.top === null; -}; + peek() { + if (this.isEmpty()) return null; + return this._data[this.size() - 1]; + } +} module.exports = Stack; @@ -39,4 +48,4 @@ module.exports = Stack; // console.log(s.peek(), 'b'); // console.log(s.pop(), 'b'); // console.log(s.pop(), 'a'); -// console.log(s.isEmpty(), true); \ No newline at end of file +// console.log(s.isEmpty(), true); diff --git a/chapter04/util/LinkedList.js b/chapter04/util/LinkedList.js index 6164dbc..ba21422 100644 --- a/chapter04/util/LinkedList.js +++ b/chapter04/util/LinkedList.js @@ -1,6 +1,84 @@ -var LinkedList = function(value) { - this.value = value; - this.next = null; -}; +// moved from chapter 2 (/util/LinkedListX.js) -module.exports = LinkedList; \ No newline at end of file +class Node { + constructor(value) { + this.value = value + this.next = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + first.next = null; + } + else this.head = null; + return first; + } + + head() { + return this.head; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } +} + +module.exports = LinkedList; diff --git a/chapter04/util/Queue.js b/chapter04/util/Queue.js index f68802a..1eeab01 100644 --- a/chapter04/util/Queue.js +++ b/chapter04/util/Queue.js @@ -1,46 +1,30 @@ // implement a queue using linkedLists -class LinkedListNode { - constructor(value) { - this.value = value; - this.next = null; - } -} +var LinkedList = require('./LinkedList'); class Queue { constructor() { - this.front = null; - this.back = null; + this._list = new LinkedList(); } enqueue(value) { - const node = new LinkedListNode(value); - if (this.front === null) { - this.front = node; - this.back = node; - } else { - var prevBack = this.back; - this.back = node; - prevBack.next = this.back; - } + this._list.append(value); } dequeue() { - const removed = this.front; - if (this.front === this.back) { - this.front = null; - this.back = null; - } else { - this.front = this.front.next; - } - return removed !== null ? removed.value : null; + let node = this._list.popFirst(); + return node.value; } peek() { - return this.front !== null ? this.front.value : null; + return this._list.head ? this._list.head.value : null; } isEmpty() { - return this.front === null; + return this._list.head == null; + } + + _toArray() { + return this._list._toArray(); } } @@ -48,7 +32,6 @@ class Queue { Queue.prototype.add = Queue.prototype.enqueue; Queue.prototype.remove = Queue.prototype.dequeue; - module.exports = Queue; /* TEST */ @@ -56,8 +39,10 @@ module.exports = Queue; // q.add('a'); // q.add('b'); // q.add('c'); +// console.log(q._toArray()); // console.log(q.remove(), 'a'); // console.log(q.peek(), 'b'); // console.log(q.remove(), 'b'); // console.log(q.remove(), 'c'); // console.log(q.isEmpty(), true); +// console.log(q._toArray()); diff --git a/chapter04/util/Stack.js b/chapter04/util/Stack.js index 99cc0ea..a04e649 100644 --- a/chapter04/util/Stack.js +++ b/chapter04/util/Stack.js @@ -1,31 +1,40 @@ -// implement a stack using linkedLists -var LinkedList = require('./LinkedList'); - -var Stack = function() { - this.top = null; -}; - -Stack.prototype.push = function(value) { - var node = new LinkedList(value); - node.next = this.top; - this.top = node; -}; - -Stack.prototype.pop = function() { - var popped = this.top; - if (this.top !== null) { - this.top = this.top.next; +// simple implementation of a stack +// using an Array + +/* +Interface: +- push(value) +- pop() +- peek() +- isEmpty() +- size() +*/ +class Stack { + constructor() { + this._data = []; } - return popped.value; -}; -Stack.prototype.peek = function() { - return this.top !== null ? this.top.value : null; -}; + size() { + return this._data.length; + } + + isEmpty() { + return this.size() == 0; + } + + push(value) { + this._data.push(value); + } + + pop() { + return this._data.pop(); + } -Stack.prototype.isEmpty = function() { - return this.top === null; -}; + peek() { + if (this.isEmpty()) return null; + return this._data[this.size() - 1]; + } +} module.exports = Stack; @@ -39,4 +48,4 @@ module.exports = Stack; // console.log(s.peek(), 'b'); // console.log(s.pop(), 'b'); // console.log(s.pop(), 'a'); -// console.log(s.isEmpty(), true); \ No newline at end of file +// console.log(s.isEmpty(), true); diff --git a/chapter07/util/LinkedList.js b/chapter07/util/LinkedList.js index 6164dbc..ba21422 100644 --- a/chapter07/util/LinkedList.js +++ b/chapter07/util/LinkedList.js @@ -1,6 +1,84 @@ -var LinkedList = function(value) { - this.value = value; - this.next = null; -}; +// moved from chapter 2 (/util/LinkedListX.js) -module.exports = LinkedList; \ No newline at end of file +class Node { + constructor(value) { + this.value = value + this.next = null; + } +} + +class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + first.next = null; + } + else this.head = null; + return first; + } + + head() { + return this.head; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } +} + +module.exports = LinkedList; diff --git a/chapter07/util/Queue.js b/chapter07/util/Queue.js index 55b8c4d..1eeab01 100644 --- a/chapter07/util/Queue.js +++ b/chapter07/util/Queue.js @@ -1,41 +1,36 @@ // implement a queue using linkedLists var LinkedList = require('./LinkedList'); -var Queue = function() { - this.front = null; - this.back = null; -}; - -Queue.prototype.add = function(value) { - var node = new LinkedList(value); - if (this.front === null) { - this.front = node; - this.back = node; - } else { - var prevBack = this.back; - this.back = node; - prevBack.next = this.back; +class Queue { + constructor() { + this._list = new LinkedList(); } -}; - -Queue.prototype.remove = function() { - var removed = this.front; - if (this.front === this.back) { - this.front = null; - this.back = null; - } else { - this.front = this.front.next; + + enqueue(value) { + this._list.append(value); + } + + dequeue() { + let node = this._list.popFirst(); + return node.value; + } + + peek() { + return this._list.head ? this._list.head.value : null; + } + + isEmpty() { + return this._list.head == null; } - return removed !== null ? removed.value : null; -}; -Queue.prototype.peek = function() { - return this.front !== null ? this.front.value : null; -}; + _toArray() { + return this._list._toArray(); + } +} -Queue.prototype.isEmpty = function() { - return this.front === null; -}; +// alias +Queue.prototype.add = Queue.prototype.enqueue; +Queue.prototype.remove = Queue.prototype.dequeue; module.exports = Queue; @@ -44,8 +39,10 @@ module.exports = Queue; // q.add('a'); // q.add('b'); // q.add('c'); +// console.log(q._toArray()); // console.log(q.remove(), 'a'); // console.log(q.peek(), 'b'); // console.log(q.remove(), 'b'); // console.log(q.remove(), 'c'); // console.log(q.isEmpty(), true); +// console.log(q._toArray()); diff --git a/chapter07/util/Stack.js b/chapter07/util/Stack.js index 99cc0ea..a04e649 100644 --- a/chapter07/util/Stack.js +++ b/chapter07/util/Stack.js @@ -1,31 +1,40 @@ -// implement a stack using linkedLists -var LinkedList = require('./LinkedList'); - -var Stack = function() { - this.top = null; -}; - -Stack.prototype.push = function(value) { - var node = new LinkedList(value); - node.next = this.top; - this.top = node; -}; - -Stack.prototype.pop = function() { - var popped = this.top; - if (this.top !== null) { - this.top = this.top.next; +// simple implementation of a stack +// using an Array + +/* +Interface: +- push(value) +- pop() +- peek() +- isEmpty() +- size() +*/ +class Stack { + constructor() { + this._data = []; } - return popped.value; -}; -Stack.prototype.peek = function() { - return this.top !== null ? this.top.value : null; -}; + size() { + return this._data.length; + } + + isEmpty() { + return this.size() == 0; + } + + push(value) { + this._data.push(value); + } + + pop() { + return this._data.pop(); + } -Stack.prototype.isEmpty = function() { - return this.top === null; -}; + peek() { + if (this.isEmpty()) return null; + return this._data[this.size() - 1]; + } +} module.exports = Stack; @@ -39,4 +48,4 @@ module.exports = Stack; // console.log(s.peek(), 'b'); // console.log(s.pop(), 'b'); // console.log(s.pop(), 'a'); -// console.log(s.isEmpty(), true); \ No newline at end of file +// console.log(s.isEmpty(), true); From 83223c211a51d3a36ae6f6e7e70e639433b18367 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Sun, 29 Mar 2020 22:56:59 +0300 Subject: [PATCH 11/24] chore: es6 rework of 3.2 (#62) --- chapter03/3.2 - Stack Min/stackMin.js | 57 +++++++++++++-------------- chapter03/util/Stack.js | 4 ++ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/chapter03/3.2 - Stack Min/stackMin.js b/chapter03/3.2 - Stack Min/stackMin.js index a818e39..4d5c4ff 100644 --- a/chapter03/3.2 - Stack Min/stackMin.js +++ b/chapter03/3.2 - Stack Min/stackMin.js @@ -1,43 +1,40 @@ var Stack = require('./../util/Stack'); // Approach, keep an additional stack that keeps the mins -var stackMin = function() { - this.stack = new Stack(); - this.minStack = new Stack(); - this.currMin = undefined; -}; - -stackMin.prototype.push = function(value) { - if (this.currMin === undefined || value <= this.currMin) { - this.minStack.push(this.currMin); - this.currMin = value; - } - this.stack.push(value); -}; -stackMin.prototype.pop = function() { - var answer = this.stack.pop(); - if (answer === this.currMin) { - this.currMin = this.minStack.pop(); +class StackMin extends Stack { + constructor() { + super(); + // additional stack to track the mins + this._minStack = new Stack(); + this._min = null; } - return answer; -}; -stackMin.prototype.peek = function() { - return this.stack.peek(); -}; + push(value) { + super.push(value); + if (this._min == null || value <= this._min) { + this._min = value; + this._minStack.push(value); + } + } -stackMin.prototype.isEmpty = function() { - return this.stack.isEmpty(); -}; + pop() { + let value = super.pop(); + if (value == this._minStack.peek()) { + this._minStack.pop(); + this._min = this._minStack.peek(); + } + return value; + } -stackMin.prototype.min = function() { - return this.currMin; -}; + min() { + return this._min; + } +} /* TEST */ -var s = new stackMin(); +var s = new StackMin(); s.push(9); s.push(8); s.push(1); @@ -57,4 +54,4 @@ console.log(s.min(), 8); s.pop(); s.pop(); console.log(s.isEmpty(), true); -console.log(s.min(), undefined); +console.log(s.min(), null); diff --git a/chapter03/util/Stack.js b/chapter03/util/Stack.js index a04e649..a84844f 100644 --- a/chapter03/util/Stack.js +++ b/chapter03/util/Stack.js @@ -34,6 +34,10 @@ class Stack { if (this.isEmpty()) return null; return this._data[this.size() - 1]; } + + _toArray() { + return this._data; + } } module.exports = Stack; From ef3b611e7f281edeb887b025781c70feaa581ac1 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Tue, 31 Mar 2020 19:54:13 +0300 Subject: [PATCH 12/24] feat: add two more linkedlist methods (#63) - insertAt(index, value) - removeAt(index) --- chapter02/util/LinkedListX.js | 90 ++++++++++++--- chapter03/util/LinkedList.js | 59 ++++++++++ chapter04/util/LinkedList.js | 212 ++++++++++++++++++++++------------ chapter07/util/LinkedList.js | 212 ++++++++++++++++++++++------------ 4 files changed, 406 insertions(+), 167 deletions(-) diff --git a/chapter02/util/LinkedListX.js b/chapter02/util/LinkedListX.js index 2bd8fdc..1e19a5b 100644 --- a/chapter02/util/LinkedListX.js +++ b/chapter02/util/LinkedListX.js @@ -18,14 +18,14 @@ class Node { this.value = value this.next = null; } -} - -class LinkedList { + } + + class LinkedList { constructor() { this.head = null; this.tail = null; } - + append(value) { let node = new Node(value); // if list is empty @@ -38,16 +38,16 @@ class LinkedList { this.tail = node; } } - + prepend(value) { let node = new Node(value); node.next = this.head; this.head = node; } - + pop() { let cur = this.head; - + // only one or no item exists if (!cur) return null; if (!cur.next) { @@ -63,7 +63,7 @@ class LinkedList { this.tail.next = null; return last; } - + popFirst() { let first = this.head; if (this.head && this.head.next) { @@ -73,15 +73,58 @@ class LinkedList { else this.head = null; return first; } - + head() { return this.head; } - + + removeAt(index) { + let i = 0; + let cur = this.head; + let prev = null; + + while (cur != null) { + if (i == index) { + // remove + if (prev == null) + this.head = cur.next; + else prev.next = cur.next; + cur.next = null; + return cur.value; + } + else { + prev = cur; + cur = cur.next; + i++; + } + } + return null; + } + + insertAt(index, value) { + if (index == 0) return this.prepend(value); + let cur = this.head; + let i = 0; + + while (cur != null) { + if (i == index - 1) { + let node = new Node(value); + node.next = cur.next; + cur.next = node; + return true; + } + else { + i++; + cur = cur.next; + } + } + return false; + } + tail() { return this.tail; } - + _toArray() { let arr = []; let cur = this.head; @@ -89,9 +132,26 @@ class LinkedList { arr.push(cur.value); cur = cur.next; } - + return arr; } -} - -module.exports = LinkedList; + } + + module.exports = LinkedList; + + /* TEST */ + + // let l = new LinkedList(); + // l.append(3); + // l.append(4); + // l.append(10); + // l.append(20); + // l.append(5); + + // console.log(l.removeAt(1), 4); + // console.log(l.pop().value, 5); + + // console.log(l._toArray()); + // l.insertAt(2, 40); + // console.log(l._toArray()); + \ No newline at end of file diff --git a/chapter03/util/LinkedList.js b/chapter03/util/LinkedList.js index ba21422..2037ae9 100644 --- a/chapter03/util/LinkedList.js +++ b/chapter03/util/LinkedList.js @@ -65,6 +65,49 @@ class LinkedList { return this.head; } + removeAt(index) { + let i = 0; + let cur = this.head; + let prev = null; + + while (cur != null) { + if (i == index) { + // remove + if (prev == null) + this.head = cur.next; + else prev.next = cur.next; + cur.next = null; + return cur.value; + } + else { + prev = cur; + cur = cur.next; + i++; + } + } + return null; + } + + insertAt(index, value) { + if (index == 0) return this.prepend(value); + let cur = this.head; + let i = 0; + + while (cur != null) { + if (i == index - 1) { + let node = new Node(value); + node.next = cur.next; + cur.next = node; + return true; + } + else { + i++; + cur = cur.next; + } + } + return false; + } + tail() { return this.tail; } @@ -82,3 +125,19 @@ class LinkedList { } module.exports = LinkedList; + +/* TEST */ + +// let l = new LinkedList(); +// l.append(3); +// l.append(4); +// l.append(10); +// l.append(20); +// l.append(5); + +// console.log(l.removeAt(1), 4); +// console.log(l.pop().value, 5); + +// console.log(l._toArray()); +// l.insertAt(2, 40); +// console.log(l._toArray()); diff --git a/chapter04/util/LinkedList.js b/chapter04/util/LinkedList.js index ba21422..67713c9 100644 --- a/chapter04/util/LinkedList.js +++ b/chapter04/util/LinkedList.js @@ -1,84 +1,144 @@ // moved from chapter 2 (/util/LinkedListX.js) class Node { - constructor(value) { - this.value = value - this.next = null; + constructor(value) { + this.value = value + this.next = null; + } } -} - -class LinkedList { - constructor() { - this.head = null; - this.tail = null; - } - - append(value) { - let node = new Node(value); - // if list is empty - if (!this.head) { - this.head = node; - this.tail = node; - } - else { - this.tail.next = node; - this.tail = node; - } - } - - prepend(value) { - let node = new Node(value); - node.next = this.head; - this.head = node; - } - - pop() { - let cur = this.head; - - // only one or no item exists - if (!cur) return null; - if (!cur.next) { - this.head = null; - return cur; - } - // move till the 2nd last - while (cur.next.next) - cur = cur.next; - - let last = this.tail; - this.tail = cur; - this.tail.next = null; - return last; - } - - popFirst() { - let first = this.head; - if (this.head && this.head.next) { - this.head = this.head.next; - first.next = null; - } - else this.head = null; - return first; - } - - head() { - return this.head; - } - - tail() { - return this.tail; - } - - _toArray() { - let arr = []; + + class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + first.next = null; + } + else this.head = null; + return first; + } + + head() { + return this.head; + } + + removeAt(index) { + let i = 0; let cur = this.head; - while (cur) { - arr.push(cur.value); + let prev = null; + + while (cur != null) { + if (i == index) { + // remove + if (prev == null) + this.head = cur.next; + else prev.next = cur.next; + cur.next = null; + return cur.value; + } + else { + prev = cur; cur = cur.next; + i++; + } } - - return arr; + return null; + } + + insertAt(index, value) { + if (index == 0) return this.prepend(value); + let cur = this.head; + let i = 0; + + while (cur != null) { + if (i == index - 1) { + let node = new Node(value); + node.next = cur.next; + cur.next = node; + return true; + } + else { + i++; + cur = cur.next; + } + } + return false; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } } -} - -module.exports = LinkedList; + + module.exports = LinkedList; + + /* TEST */ + + // let l = new LinkedList(); + // l.append(3); + // l.append(4); + // l.append(10); + // l.append(20); + // l.append(5); + + // console.log(l.removeAt(1), 4); + // console.log(l.pop().value, 5); + + // console.log(l._toArray()); + // l.insertAt(2, 40); + // console.log(l._toArray()); + \ No newline at end of file diff --git a/chapter07/util/LinkedList.js b/chapter07/util/LinkedList.js index ba21422..67713c9 100644 --- a/chapter07/util/LinkedList.js +++ b/chapter07/util/LinkedList.js @@ -1,84 +1,144 @@ // moved from chapter 2 (/util/LinkedListX.js) class Node { - constructor(value) { - this.value = value - this.next = null; + constructor(value) { + this.value = value + this.next = null; + } } -} - -class LinkedList { - constructor() { - this.head = null; - this.tail = null; - } - - append(value) { - let node = new Node(value); - // if list is empty - if (!this.head) { - this.head = node; - this.tail = node; - } - else { - this.tail.next = node; - this.tail = node; - } - } - - prepend(value) { - let node = new Node(value); - node.next = this.head; - this.head = node; - } - - pop() { - let cur = this.head; - - // only one or no item exists - if (!cur) return null; - if (!cur.next) { - this.head = null; - return cur; - } - // move till the 2nd last - while (cur.next.next) - cur = cur.next; - - let last = this.tail; - this.tail = cur; - this.tail.next = null; - return last; - } - - popFirst() { - let first = this.head; - if (this.head && this.head.next) { - this.head = this.head.next; - first.next = null; - } - else this.head = null; - return first; - } - - head() { - return this.head; - } - - tail() { - return this.tail; - } - - _toArray() { - let arr = []; + + class LinkedList { + constructor() { + this.head = null; + this.tail = null; + } + + append(value) { + let node = new Node(value); + // if list is empty + if (!this.head) { + this.head = node; + this.tail = node; + } + else { + this.tail.next = node; + this.tail = node; + } + } + + prepend(value) { + let node = new Node(value); + node.next = this.head; + this.head = node; + } + + pop() { + let cur = this.head; + + // only one or no item exists + if (!cur) return null; + if (!cur.next) { + this.head = null; + return cur; + } + // move till the 2nd last + while (cur.next.next) + cur = cur.next; + + let last = this.tail; + this.tail = cur; + this.tail.next = null; + return last; + } + + popFirst() { + let first = this.head; + if (this.head && this.head.next) { + this.head = this.head.next; + first.next = null; + } + else this.head = null; + return first; + } + + head() { + return this.head; + } + + removeAt(index) { + let i = 0; let cur = this.head; - while (cur) { - arr.push(cur.value); + let prev = null; + + while (cur != null) { + if (i == index) { + // remove + if (prev == null) + this.head = cur.next; + else prev.next = cur.next; + cur.next = null; + return cur.value; + } + else { + prev = cur; cur = cur.next; + i++; + } } - - return arr; + return null; + } + + insertAt(index, value) { + if (index == 0) return this.prepend(value); + let cur = this.head; + let i = 0; + + while (cur != null) { + if (i == index - 1) { + let node = new Node(value); + node.next = cur.next; + cur.next = node; + return true; + } + else { + i++; + cur = cur.next; + } + } + return false; + } + + tail() { + return this.tail; + } + + _toArray() { + let arr = []; + let cur = this.head; + while (cur) { + arr.push(cur.value); + cur = cur.next; + } + + return arr; + } } -} - -module.exports = LinkedList; + + module.exports = LinkedList; + + /* TEST */ + + // let l = new LinkedList(); + // l.append(3); + // l.append(4); + // l.append(10); + // l.append(20); + // l.append(5); + + // console.log(l.removeAt(1), 4); + // console.log(l.pop().value, 5); + + // console.log(l._toArray()); + // l.insertAt(2, 40); + // console.log(l._toArray()); + \ No newline at end of file From f20694609255d5a45e6215770fa8e6215c5faa8f Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Tue, 31 Mar 2020 21:25:57 +0300 Subject: [PATCH 13/24] fix(3.3): implement with stack + bug fixes (#64) * chore: rewrite 3.3 in ES6 * fix(3.3): bug fix for pop - this clears an empty stack after a pop, instead of checking in the next pop * fix(3.3): fix popAt bug - so as to handle exhausting popAt's * fix(3.3): implement with stack adt --- .../3.3 - Stack of Plates/stackOfPlates.js | 93 +++++++++++-------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/chapter03/3.3 - Stack of Plates/stackOfPlates.js b/chapter03/3.3 - Stack of Plates/stackOfPlates.js index 3fe3bdf..7232bfb 100644 --- a/chapter03/3.3 - Stack of Plates/stackOfPlates.js +++ b/chapter03/3.3 - Stack of Plates/stackOfPlates.js @@ -1,40 +1,59 @@ -var SetOfStacks = function(capacity) { - // implement as an array of stacks - this.capacity = capacity; - this.stackSet = []; -}; +// implement as array of stacks +const Stack = require("../util/Stack"); -SetOfStacks.prototype.push = function(value) { - if (this.stackSet.length === 0 || this.stackSet[this.stackSet.length - 1].length === this.capacity) { - var newStack = []; - newStack.push(value); - this.stackSet.push(newStack); - } else { - this.stackSet[this.stackSet.length - 1].push(value); +class SetOfStacks { + constructor(capacity) { + this.capacity = capacity; + this.stackSet = []; } -}; -SetOfStacks.prototype.pop = function() { - if (this.numStack === 0) { - return undefined; - } else if (this.stackSet[this.stackSet.length - 1].length === 0) { - this.stackSet.pop(); - } - return this.stackSet[this.stackSet.length - 1].pop(); -}; + getLastStack() { + return this.stackSet[this.stackSet.length - 1]; + } + + push(value) { + let last = this.getLastStack(); + if (this.stackSet.length === 0 || last.size() === this.capacity) { + var newStack = new Stack(); + newStack.push(value); + this.stackSet.push(newStack); + } else { + last.push(value); + } + } -SetOfStacks.prototype.peek = function() { - var currStack = this.stackSet[this.stackSet.length - 1]; - return currStack[currStack.length - 1]; -}; + pop() { + if (this.stackSet.length === 0) { + return undefined; + } + let last = this.getLastStack(); + let value = last.pop(); + if (last.size() === 0) { + this.stackSet.pop(); + } + return value; + } + + peek() { + let last = this.getLastStack(); + return last.peek(); + } -SetOfStacks.prototype.isEmpty = function() { - return this.stackSet.length === 0; -}; + isEmpty() { + return this.stackSet.length === 0; + } -SetOfStacks.prototype.popAt = function(index) { - return this.stackSet[index].pop(); -}; + popAt(index) { + // out of range index + if (index < 0 || index >= this.stackSet.length) return false; + let value = this.stackSet[index].pop(); + if (this.stackSet[index].size() == 0) { + // clear the stack from the set + this.stackSet.splice(index, 1); + } + return value; + } +} /* TESTS */ @@ -54,11 +73,13 @@ s.push(12); s.push(13); s.push(14); -console.log(s.stackSet); +console.log(s.peek(), 14); +s.popAt(2); +s.popAt(2); s.popAt(2); -console.log(s.stackSet); +console.log(s.peek(), 14); s.pop(); s.pop(); @@ -70,8 +91,4 @@ s.pop(); s.pop(); s.pop(); -console.log(s.stackSet); - - -// Note: if stack not implemented as an array, would need to separately keep track of the depth -// of each stack in an array +console.log(s.peek(), 2); From 47d7a9c754d9cad78e7fef0e54e3975b225a8e95 Mon Sep 17 00:00:00 2001 From: Anthony Nandaa Date: Tue, 31 Mar 2020 22:39:20 +0300 Subject: [PATCH 14/24] chore(3.4): rewrite to es6 (#65) --- .../3.4 - Queue via Stacks/queueViaStacks.js | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/chapter03/3.4 - Queue via Stacks/queueViaStacks.js b/chapter03/3.4 - Queue via Stacks/queueViaStacks.js index bb9f48e..c205431 100644 --- a/chapter03/3.4 - Queue via Stacks/queueViaStacks.js +++ b/chapter03/3.4 - Queue via Stacks/queueViaStacks.js @@ -1,47 +1,49 @@ var Stack = require('./../util/Stack'); -var myQueue = function() { - this.front = new Stack(); - this.back = new Stack(); - this.backUp = true; -}; +class MyQueue { + constructor() { + this.front = new Stack(); + this.back = new Stack(); + this.backUp = true; + } -myQueue.prototype.add = function(value) { - if (!this.backUp) { - while (!this.front.isEmpty()) { - this.back.push(this.front.pop()); + add(value) { + if (!this.backUp) { + while (!this.front.isEmpty()) { + this.back.push(this.front.pop()); + } + this.backUp = true; } - this.backUp = true; + this.back.push(value); } - this.back.push(value); -}; -myQueue.prototype.remove = function() { - if (this.backUp) { - while(!this.back.isEmpty()) { - this.front.push(this.back.pop()); + remove() { + if (this.backUp) { + while(!this.back.isEmpty()) { + this.front.push(this.back.pop()); + } + this.backUp = false; } - this.backUp = false; + return this.front.pop(); } - return this.front.pop(); -}; -myQueue.prototype.peek = function() { - if (this.backUp) { - while(!this.back.isEmpty()) { - this.front.push(this.back.pop()); + peek() { + if (this.backUp) { + while(!this.back.isEmpty()) { + this.front.push(this.back.pop()); + } + this.backUp = false; } - this.backUp = false; + return this.front.peek(); } - return this.front.peek(); -}; -myQueue.prototype.isEmpty = function() { - return this.front.isEmpty() && this.back.isEmpty(); -}; + isEmpty() { + return this.front.isEmpty() && this.back.isEmpty(); + } +} /* TEST */ -var m = new myQueue(); +var m = new MyQueue(); console.log(m.isEmpty(), true); m.add('a'); From 96b534fdd53288d3c507f73943feb6e46075495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CA=95=C2=B4=E2=80=A2=20=E1=B4=A5=20=E2=80=A2=60=CA=94?= <12530451+saoirse-zee@users.noreply.github.com> Date: Mon, 6 Apr 2020 13:19:42 -0400 Subject: [PATCH 15/24] feat: added another answer for chp.1 q4 (#66) --- chapter01/1.4 - PalinPerm/palinPerm2.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 chapter01/1.4 - PalinPerm/palinPerm2.js diff --git a/chapter01/1.4 - PalinPerm/palinPerm2.js b/chapter01/1.4 - PalinPerm/palinPerm2.js new file mode 100644 index 0000000..bf0f525 --- /dev/null +++ b/chapter01/1.4 - PalinPerm/palinPerm2.js @@ -0,0 +1,20 @@ +function palinPerm(s) { + const sanitized = s.toUpperCase().split(" ").join(""); + const freq = new Map(); + for (let i = 0; i < sanitized.length; i++) { + const char = sanitized.charAt(i); + const prevFreq = freq.get(char) || 0; + freq.set(char, prevFreq + 1); + } + let oddCount = 0; + for (let char of freq) { + if (char[1] % 2 !== 0) { + oddCount++; + } + } + return oddCount < 2; +} + +// TESTS +console.log(palinPerm('Tact Coa'), 'true'); +console.log(palinPerm('Tact boa'), 'false'); From 7f1387f3f43d451952a30cbb5f35c6fb22f95b36 Mon Sep 17 00:00:00 2001 From: Charity Marani Date: Wed, 8 Apr 2020 22:20:49 +0300 Subject: [PATCH 16/24] fix(2.2): redo returnKthToLast (#67) --- .../returnKthToLast.js | 63 +++++++++---------- .../deleteMiddleNode.js | 55 +++++----------- 2 files changed, 45 insertions(+), 73 deletions(-) diff --git a/chapter02/2.2 - Return Kth to Last/returnKthToLast.js b/chapter02/2.2 - Return Kth to Last/returnKthToLast.js index 7d3b742..5c740e1 100644 --- a/chapter02/2.2 - Return Kth to Last/returnKthToLast.js +++ b/chapter02/2.2 - Return Kth to Last/returnKthToLast.js @@ -1,42 +1,41 @@ -var linkedList = function(value) { - this.value = value; - this.next = null; -}; +const LinkedList = require("../util/LinkedListX"); + +var findKthToLast = function(k, list) { + // do iteratively + //define two pointers , fast and slow pointer + let fast = list.head + let slow = list.head + + //Move fast pointer k steps in the linkedlist while slow remains at head + for(let i=0;i b -> c -> d -> e -> f, input c -// a -> b -> *d -> d -> e -> f -// a -> b -> d -> *e -> e -> f -// a -> b -> d -> e -> *f -> f -// a -> b -> d -> e -> f -> *null - /* TEST */ -var printList = function(head) { - while(head !== null) { - console.log(head.value); - head = head.next; - } - console.log('done printing'); -}; - -var a = new LinkedList('a'); -var b = new LinkedList('b'); -var c = new LinkedList('c'); -var d = new LinkedList('d'); -var e = new LinkedList('e'); -var f = new LinkedList('f'); - -a.next = b; -b.next = c; -c.next = d; -d.next = e; -e.next = f; +let list = new LinkedList(); +for (let item of [1, 2, 3, 4, 5, 6]) { + list.append(item); +} -printList(a); -deleteMidNode(c); -printList(a); +printList(list.head); +deleteMidNode(list.head.next); +printList(list.head); From f6ae3077f3e2ae7cc28c0d718d7a138443f017dc Mon Sep 17 00:00:00 2001 From: Rajasimha Reddy Date: Wed, 27 May 2020 20:36:06 +0530 Subject: [PATCH 17/24] fix: update isUnique.js (#68) * Update isUnique.js Using an object to store the occurrences, and check for duplication * Update isUnique.js --- chapter01/1.1 - Is Unique/isUnique.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/chapter01/1.1 - Is Unique/isUnique.js b/chapter01/1.1 - Is Unique/isUnique.js index 002644e..3321571 100644 --- a/chapter01/1.1 - Is Unique/isUnique.js +++ b/chapter01/1.1 - Is Unique/isUnique.js @@ -23,6 +23,18 @@ const everyCharUnique = (str, indexOffset = 'a'.charCodeAt()) => { return true; }; +function everyCharUnique(str) { + let obj = {}; + for (let i = 0; i < str.length; i++) { + if (obj[str[i]] && obj[str[i]] >= 1) { + return false; + } else { + obj[str[i]] = 1; + } + } + return true; +} + /* TESTS */ console.log(everyCharUnique('abcd'), 'true'); console.log(everyCharUnique('abccd'), 'false'); From e7b402e8fe60f3a31fbdcd552f888ba6e7e54aec Mon Sep 17 00:00:00 2001 From: Carlos Green <30880055+greenc123@users.noreply.github.com> Date: Wed, 19 Aug 2020 09:42:53 -0700 Subject: [PATCH 18/24] chore: update animalShelter.js (#70) --- chapter03/3.6 - Animal Shelter/animalShelter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapter03/3.6 - Animal Shelter/animalShelter.js b/chapter03/3.6 - Animal Shelter/animalShelter.js index 342f14d..73471d1 100644 --- a/chapter03/3.6 - Animal Shelter/animalShelter.js +++ b/chapter03/3.6 - Animal Shelter/animalShelter.js @@ -12,7 +12,7 @@ var AnimalShelter = function() { AnimalShelter.prototype.enqueue = function(animal) { if (animal.type === 'dog') { this.dogQ.enqueue(animal); - } else if (animal.type === 'vat') { + } else if (animal.type === 'cat') { this.catQ.enqueue(animal); } this.allQ.enqueue(animal); From 1606b02399a4bbe0f1424d8df2643f023d7a8a76 Mon Sep 17 00:00:00 2001 From: Catherine Cheng Date: Sat, 27 Feb 2021 18:57:58 -0800 Subject: [PATCH 19/24] fix(5.1):use bit mask and bit operators (#80) --- chapter05/5.1 - Insertion/insertion.js | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/chapter05/5.1 - Insertion/insertion.js b/chapter05/5.1 - Insertion/insertion.js index f7c05fa..350df6b 100644 --- a/chapter05/5.1 - Insertion/insertion.js +++ b/chapter05/5.1 - Insertion/insertion.js @@ -1,14 +1,11 @@ -var insertion = function(N, M, i, j) { - var n = N.split(''); - var m = M.split(''); - var nlength = n.length - 1; - var mlength = m.length - 1; - for (var a = 0; a < j - i + 1; a++) { - console.log(m[mlength - a]); - n[nlength - (i + a)] = m[mlength - a]; - } - return n.join(''); +const insertion = (N, M, i, j) => { + const bitMask = (-1 << (j + 1)) | ((1 << i) - 1); + const clearedN = N & bitMask; + const shiftedM = M << i; + return clearedN | shiftedM; }; /* TEST */ -console.log(insertion('10000000000', '10011', 2, 6), '10001001100'); \ No newline at end of file +const N = parseInt(10000000000, 2); +const M = parseInt(10011, 2); +console.log(insertion(M, N, 2, 6).toString(2), 10001001100); From bea811c3f0913359c29c62abf5493e61d8ba5c16 Mon Sep 17 00:00:00 2001 From: Carlos Green <30880055+greenc123@users.noreply.github.com> Date: Mon, 24 May 2021 10:52:40 -0700 Subject: [PATCH 20/24] 8.01 Triple step (#77) * tripleStep Backtracking, Top Down and Bottom up memoization implementation * removed comments * removed more comments * 8.01 tripleStep O(1) or constant space * removed multi-line comment * less bloating code for triple step * constant space solution * tripleStep version 2 * original and tripleStepv2 * formatted code * added TEST comment * added whitespace so both origin files are the same --- chapter08/8.01 - Triple Step/tripleStepv2.js | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 chapter08/8.01 - Triple Step/tripleStepv2.js diff --git a/chapter08/8.01 - Triple Step/tripleStepv2.js b/chapter08/8.01 - Triple Step/tripleStepv2.js new file mode 100644 index 0000000..f694105 --- /dev/null +++ b/chapter08/8.01 - Triple Step/tripleStepv2.js @@ -0,0 +1,64 @@ +/* +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, res = 0) { + 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 memo[0]; + if (n === 1) return memo[n]; + if (i > n) return memo[memo.length - 1]; + + 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); From 05e701b1ef12a52a9c87e401d39f8751ea7e279d Mon Sep 17 00:00:00 2001 From: Kapil Raghuwanshi Date: Wed, 2 Jun 2021 21:01:07 +0530 Subject: [PATCH 21/24] 3.1: Removed unused value in pop3() operation (#82) Line no 47 --- chapter03/3.1 - Three in One/threeInOne.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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() { From 88b95fd0c86b0b137a7f5e60fecb2a2ba7f66b8e Mon Sep 17 00:00:00 2001 From: Carlos Green Date: Sat, 28 Jan 2023 11:06:28 -0800 Subject: [PATCH 22/24] fix: remove bloat in triple step (#86) --- chapter08/8.01 - Triple Step/tripleStepv2.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/chapter08/8.01 - Triple Step/tripleStepv2.js b/chapter08/8.01 - Triple Step/tripleStepv2.js index f694105..e41f6b3 100644 --- a/chapter08/8.01 - Triple Step/tripleStepv2.js +++ b/chapter08/8.01 - Triple Step/tripleStepv2.js @@ -8,7 +8,7 @@ Recursion and Dynamic Programming (4 steps) // Recursive Backtracking // Time & Space O(n!) -function tripleStep(n, res = 0) { +function tripleStep(n) { if (n < 0) return 0; if (n === 0) return 1; return tripleStep(n + 1) + tripleStep(n - 2) + tripleStep(n - 3); @@ -17,10 +17,8 @@ function tripleStep(n, res = 0) { // Top Down Memoization // Time & Space O(n) function tripleStep(n, i = 3, memo = [1, 1, 2, 4]) { - if (n < 0) return memo[0]; - if (n === 1) return memo[n]; - if (i > n) return memo[memo.length - 1]; - + 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); } From 9553d4754ebaf92b88502322a1cadd09705acbc4 Mon Sep 17 00:00:00 2001 From: Kapil Raghuwanshi Date: Sun, 29 Jan 2023 00:41:47 +0530 Subject: [PATCH 23/24] fix: replaced "n+1" to "n-1" in triple-step (#88) It could be a typo but wrong solution. --- chapter08/8.01 - Triple Step/tripleStepv2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapter08/8.01 - Triple Step/tripleStepv2.js b/chapter08/8.01 - Triple Step/tripleStepv2.js index e41f6b3..32ae4d8 100644 --- a/chapter08/8.01 - Triple Step/tripleStepv2.js +++ b/chapter08/8.01 - Triple Step/tripleStepv2.js @@ -11,7 +11,7 @@ Recursion and Dynamic Programming (4 steps) function tripleStep(n) { if (n < 0) return 0; if (n === 0) return 1; - return tripleStep(n + 1) + tripleStep(n - 2) + tripleStep(n - 3); + return tripleStep(n - 1) + tripleStep(n - 2) + tripleStep(n - 3); } // Top Down Memoization From 33830739629d3d3f9a4b0f122ba5150431a9d506 Mon Sep 17 00:00:00 2001 From: Kapil Raghuwanshi Date: Sun, 29 Jan 2023 00:44:07 +0530 Subject: [PATCH 24/24] new soln: find duplicate, 10.08 (#84) --- .../10.08 - Find Duplicates/findDuplicates.js | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) 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]