diff --git a/README.md b/README.md index fd888d40..dc772666 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,12 @@ Collection of interview questions with Unit Tests. Problems includes Data Struct - [Remove Consecutive Repeated Digits](src/_DataStructures_/Stack/remove-consecutive-repeated-digits) - [Implement 2 Stacks using Single Array](src/_DataStructures_/Stack/2-stacks-using1-array) - - [Queue](src/_DataStructures_/Queue) - [Weave](src/_DataStructures_/Queue/weave) + - [Reverse First K Elements of a Queue](src/_DataStructures_/Queue/reverse-first-k) + - [Generate all Binary Numbers from 1 to N](src/_DataStructures_/Queue/generate-binary-number) + - [Queue using Stack](src/_DataStructures_/Queue/queue-using-stack) - [Doubly Linked List](src/_DataStructures_/DoublyLinkedList) diff --git a/src/_DataStructures_/LinkedList/index.js b/src/_DataStructures_/LinkedList/index.js index 1704c3c4..e7964c01 100644 --- a/src/_DataStructures_/LinkedList/index.js +++ b/src/_DataStructures_/LinkedList/index.js @@ -8,32 +8,44 @@ class Node { class LinkedList { constructor() { this.head = null; + this.tail = null; + this.size = 0; } addAtBeginning(element) { this.head = new Node(element, this.head); + if (!this.tail) { + this.tail = this.head; + } + this.size += 1; + return this.head; } addAtEnd(element) { const node = new Node(element, null); + this.size += 1; if (!this.head) { this.head = node; - } else { - let address = this.head; - while (address.next) { - address = address.next; - } - address.next = node; + this.tail = node; + return node; } + this.tail.next = node; + this.tail = node; + return node; } removeFromBeginning() { if (!this.head) { return null; } + if (this.head.next === null) { + this.tail = this.head; + } const node = this.head; this.head = this.head.next; + this.size -= 1; + node.next = null; return node; } @@ -47,8 +59,11 @@ class LinkedList { address = address.next; } - const node = address.next; - address.next = null; + this.tail = address; + + const node = this.tail.next; + this.tail.next = null; + this.size -= 1; return node; } @@ -63,11 +78,7 @@ class LinkedList { if (!this.head) { return null; } - let address = this.head; - while (address.next) { - address = address.next; - } - return address; + return this.tail; } getAt(index) { @@ -104,8 +115,10 @@ class LinkedList { count -= 1; } - previous.next = new Node(element, previous.next); - return null; + const node = new Node(element, previous.next); + previous.next = node; + this.size += 1; + return node; } removeAt(index) { @@ -129,21 +142,19 @@ class LinkedList { const node = address; previous.next = address.next.next; + this.size -= 1; + node.next = null; return node; } length() { - let address = this.head; - let count = 0; - while (address) { - count += 1; - address = address.next; - } - return count; + return this.size; } delete() { this.head = null; + this.tail = this.head; + this.size = 0; } } diff --git a/src/_DataStructures_/Queue/Queue.test.js b/src/_DataStructures_/Queue/Queue.test.js index ebe7205c..bdbc6f26 100644 --- a/src/_DataStructures_/Queue/Queue.test.js +++ b/src/_DataStructures_/Queue/Queue.test.js @@ -12,23 +12,24 @@ describe('Data Structure : Queue', () => { queue = new Queue(); }); - it('Should add() element to a queue', () => { - queue.add(5); - expect(queue.data).toEqual([5]); + it('Should add element to a queue', () => { + queue.enqueue(5); + expect(queue.peek()).toEqual(5); }); - it('Should remove() an element from the queue', () => { - queue.add(2); - queue.add(3); + it('Should dequeue() an element from the queue', () => { + queue.enqueue(2); + queue.enqueue(3); - expect(queue.remove()).toEqual(2); - expect(queue.data).toEqual([3]); + expect(queue.dequeue()).toEqual(2); + expect(queue.peek()).toEqual(3); + expect(queue.length()).toEqual(1); }); describe('peek()', () => { beforeEach(() => { - queue.add(2); - queue.add(5); + queue.enqueue(2); + queue.enqueue(5); }); it('Should return the elemet to be removed using peek()', () => { @@ -37,21 +38,21 @@ describe('Data Structure : Queue', () => { it('Should not remove the element', () => { expect(queue.peek()).toEqual(2); - expect(queue.remove()).toEqual(2); + expect(queue.dequeue()).toEqual(2); }); }); it('Should maintain the order of elements', () => { // first in first out - queue.add(2); - queue.add(1); - queue.add(4); - queue.add(3); - - expect(queue.remove()).toEqual(2); - expect(queue.remove()).toEqual(1); - expect(queue.remove()).toEqual(4); - expect(queue.remove()).toEqual(3); + queue.enqueue(2); + queue.enqueue(1); + queue.enqueue(4); + queue.enqueue(3); + + expect(queue.dequeue()).toEqual(2); + expect(queue.dequeue()).toEqual(1); + expect(queue.dequeue()).toEqual(4); + expect(queue.dequeue()).toEqual(3); }); }); }); diff --git a/src/_DataStructures_/Queue/QueueUsingArray.js b/src/_DataStructures_/Queue/QueueUsingArray.js new file mode 100644 index 00000000..99d1861c --- /dev/null +++ b/src/_DataStructures_/Queue/QueueUsingArray.js @@ -0,0 +1,20 @@ +class Queue { + constructor() { + this.data = []; + } + + add(element) { + // add element to the start of the data + return this.data.unshift(element); + } + + peek() { + return this.data[this.data.length - 1]; + } + + remove() { + return this.data.pop(); + } +} + +module.exports = Queue; diff --git a/src/_DataStructures_/Queue/generate-binary-number/index.js b/src/_DataStructures_/Queue/generate-binary-number/index.js new file mode 100644 index 00000000..feea197b --- /dev/null +++ b/src/_DataStructures_/Queue/generate-binary-number/index.js @@ -0,0 +1,29 @@ +const Queue = require('../index'); + +function generateBinaryNumber(n) { + const result = []; + const q = new Queue(); + + // add `1` to the queue + q.enqueue('1'); + + // iterate till the given number + for (let i = 0; i < n; i += 1) { + // push the item in the queue to the array + result.push(q.dequeue()); + + // append `0` & `1` respectively + const s1 = `${result[i]}0`; + const s2 = `${result[i]}1`; + + // push the combinations in the queue + q.enqueue(s1); + q.enqueue(s2); + } + // return the result containing all the binary numbers + return result; +} + +// console.log(generateBinaryNumber(5)); + +module.exports = generateBinaryNumber; diff --git a/src/_DataStructures_/Queue/index.js b/src/_DataStructures_/Queue/index.js index d51bcab0..9056c130 100644 --- a/src/_DataStructures_/Queue/index.js +++ b/src/_DataStructures_/Queue/index.js @@ -1,20 +1,57 @@ -class Queue { +const { LinkedList: SinglyLinkedLists } = require('../LinkedList'); + +class Queue extends SinglyLinkedLists { constructor() { - this.data = []; + super(); + this.NotAllowed = 'Not Allowed'; + } + + enqueue(data) { + return this.addAtEnd(data); } - add(element) { - // add element to the start of the data - return this.data.unshift(element); + dequeue() { + const node = this.removeFromBeginning(); + return node ? node.data : node; } peek() { - return this.data[this.data.length - 1]; + const node = this.getFirst(); + return node ? node.data : node; + } + + length() { + return this.size; + } + + destroy() { + this.delete(); + } + + /** Override and throw error for other LL methods */ + addAtBeginning() { + throw new Error(this.NotAllowed); + } + + addAt() { + throw new Error(this.NotAllowed); + } + + removeFromEnd() { + throw new Error(this.NotAllowed); + } + + getLast() { + throw new Error(this.NotAllowed); + } + + getAt() { + throw new Error(this.NotAllowed); } - remove() { - return this.data.pop(); + removeAt() { + throw new Error(this.NotAllowed); } } -module.exports = Queue; \ No newline at end of file +module.exports = Queue; diff --git a/src/_DataStructures_/Queue/queue-using-stack/index.js b/src/_DataStructures_/Queue/queue-using-stack/index.js new file mode 100644 index 00000000..dbaf6960 --- /dev/null +++ b/src/_DataStructures_/Queue/queue-using-stack/index.js @@ -0,0 +1,28 @@ +const Stack = require('../../Stack'); + +class Queue { + constructor() { + this.queue = new Stack(); + this.temp = new Stack(); + } + + enqueue(data) { + this.queue.push(data); + } + + dequeue() { + if (!this.queue.peek()) { + return null; + } + + // pop all the element to the temp stack + while (this.queue.peek()) this.temp.push(this.queue.pop()); + const el = this.temp.pop(); + + // push all the temp items to the queue again + while (this.temp.peek()) this.queue.push(this.temp.pop()); + return el; + } +} + +module.exports = Queue; diff --git a/src/_DataStructures_/Queue/reverse-first-k/index.js b/src/_DataStructures_/Queue/reverse-first-k/index.js new file mode 100644 index 00000000..7d9ccf37 --- /dev/null +++ b/src/_DataStructures_/Queue/reverse-first-k/index.js @@ -0,0 +1,48 @@ +// eslint-disable-next-line no-unused-vars +const Queue = require('../index'); +const Stack = require('../../Stack'); + +function reverseFirstKElelments(q, k) { + const s = new Stack(); + + // push all the k elements ot the stack + for (let i = 0; i < k; i += 1) { + s.push(q.dequeue()); + } + + // push the stack items to the queue + for (let i = 0; i < k; i += 1) { + q.enqueue(s.pop()); + } + + // empty the queue and push the same queue + const remaining = q.length() - k; + for (let i = 0; i < remaining; i += 1) { + q.enqueue(q.dequeue()); + } + + // return the queue + return q; +} + +module.exports = reverseFirstKElelments; + +// let q = new Queue(); + +// q.enqueue(1); +// q.enqueue(2); +// q.enqueue(3); +// q.enqueue(4); +// q.enqueue(5); +// q.enqueue(6); +// q.enqueue(7); +// q.enqueue(8); +// q.enqueue(9); + +// q = reverseFirstKElelments(q, 4); + +// const arr = []; +// while (q.length()) { +// arr.push(q.dequeue()); +// } +// console.log(arr); diff --git a/src/_DataStructures_/Queue/weave/index.js b/src/_DataStructures_/Queue/weave/index.js index 94d1d660..5a6da801 100644 --- a/src/_DataStructures_/Queue/weave/index.js +++ b/src/_DataStructures_/Queue/weave/index.js @@ -4,12 +4,12 @@ function weaveQueues(first, second) { const weaved = new Queue(); while (first.peek() || second.peek()) { - if (first.peek() !== undefined) { - weaved.add(first.remove()); + if (first.peek()) { + weaved.enqueue(first.dequeue()); } - if (second.peek() !== undefined) { - weaved.add(second.remove()); + if (second.peek()) { + weaved.enqueue(second.dequeue()); } } return weaved; diff --git a/src/_DataStructures_/Queue/weave/weave.test.js b/src/_DataStructures_/Queue/weave/weave.test.js index da307f36..05c43ec0 100644 --- a/src/_DataStructures_/Queue/weave/weave.test.js +++ b/src/_DataStructures_/Queue/weave/weave.test.js @@ -10,18 +10,18 @@ describe('Weave two queues using weaveQueues()', () => { const q1 = new Queue(); const q2 = new Queue(); - q1.add('Hello'); - q2.add(1); - q1.add('World'); - q2.add(2); - q2.add(3); + q1.enqueue('Hello'); + q2.enqueue(1); + q1.enqueue('World'); + q2.enqueue(2); + q2.enqueue(3); const q3 = weaveQueues(q1, q2); - expect(q3.remove()).toEqual('Hello'); - expect(q3.remove()).toEqual(1); - expect(q3.remove()).toEqual('World'); - expect(q3.remove()).toEqual(2); - expect(q3.remove()).toEqual(3); + expect(q3.dequeue()).toEqual('Hello'); + expect(q3.dequeue()).toEqual(1); + expect(q3.dequeue()).toEqual('World'); + expect(q3.dequeue()).toEqual(2); + expect(q3.dequeue()).toEqual(3); }); }); diff --git a/src/_DataStructures_/Stack/index.js b/src/_DataStructures_/Stack/index.js index 4836ae65..9e6c7613 100644 --- a/src/_DataStructures_/Stack/index.js +++ b/src/_DataStructures_/Stack/index.js @@ -15,8 +15,10 @@ class Stack { peek() { return this.data[this.data.length - 1]; } - isEmpty(){ //check if stack is empty - return this.data.length==0; + + isEmpty() { + // check if stack is empty + return this.data.length === 0; } }