├── .DS_Store ├── 1.Arrays ├── 1.TwoSum │ └── solution.js ├── 2.ReverseAString │ └── solution.js ├── 3.TwoSum2InputIsSorted │ └── solution.js ├── 4.SquareOfSortedArray │ └── solution.js ├── Notes1.pdf ├── Notes2.pdf └── sortfunctiondemo.js ├── 10.Deque ├── Dll.js ├── deque.js ├── lrucache.js ├── maximumSlidingWindowOfSizeK.js └── notes1.pdf ├── 11.BinaryTree ├── BT.js ├── FlipEquivalent.js ├── MaxWidthOfABt.js ├── balancedBT.js ├── constructStringfromBT.js ├── diameterofaBT.js ├── duplicatesubtrees.js ├── houseRobber3.js ├── inorder.js ├── invertBinaryTree.js ├── levelOrderLevelWise.js ├── maximumDepth.js ├── notes.pdf ├── notes2.pdf ├── notes3.pdf ├── notes4.pdf ├── portorder.js ├── preorder.js └── sumroottoleaf.js ├── 12.BST ├── insertInABST.js ├── notes 2.pdf ├── notes1.pdf └── sortedListToBST.js ├── 13.Hashing ├── HashMap.js ├── notes.pdf └── test.js ├── 14.Trie ├── notes.pdf └── trie.js ├── 15. AVL ├── avl.js └── notes1.pdf ├── 16.Heaps ├── GenericHeap.js ├── KclosespointtoOrigin.js ├── heap.js ├── kthsmallestperimefraction.js ├── mergeksorteslists.js ├── notes.pdf └── notes2.pdf ├── 17.Graphs ├── ChecIfPathExistUsingBfs.js ├── CheckIfPathExist.js ├── RottenOranges.js ├── adjacencyMatrix.js ├── courseSchedule1.js ├── courseSchedule2.js ├── dijkstra.js ├── dsu.js ├── graph.js ├── kruskals.js ├── maxAreaOfIsland.js ├── notes1.pdf ├── notes2.pdf ├── notes3.pdf ├── notes4.pdf ├── notes5.pdf ├── numberOfIslands.js └── shortCutGraph.js ├── 2.ArraysAndHashing └── 1.ValidAnagram │ └── solution.js ├── 3.TimeComplexity └── notes.pdf ├── 4.Sorting ├── bubblesort.class ├── bubblesort.java ├── insertionsrot.class ├── insertionsrot.java ├── merge2sortedarrays.java ├── mergesort.class ├── mergesort.java ├── notes.pdf ├── notes2.pdf ├── selectionSort.class ├── selectionSort.java └── selectionsort.js ├── 5.Searching ├── ArrangingCoins.java ├── ArrangingCoins.js ├── BinarySearch.java ├── CapacityToShipPackages.java ├── CapacityToShipPackages.js ├── FindFirstAndLastPositionOfElement.java ├── FindFirstAndLastPositionOfElement.js ├── GuessNumberHigherOrLower.java ├── GuessNumberHigherOrLower.js ├── MinimizeTheMaximumDifferencePair.java ├── Notes2.pdf ├── PeakElement.java ├── PeakElement.js ├── Search2dMatrix.java ├── Search2dMatrix.js ├── SplitArrayLargestSum.java ├── UpperBound.class ├── UpperBound.java ├── binarysearch.js ├── kokoeatingbananas.java ├── kokoeatingbananas.js ├── lowerBound.class ├── lowerBound.java ├── lowerBound.js ├── notes 4.pdf ├── notes1.pdf ├── notes3.pdf └── upperbound.js ├── 6.DP ├── ArithmeticSlices.java ├── ArithmeticSlices.js ├── ArithmeticSlices2.java ├── ArithmeticSlices2.js ├── CoinChange.java ├── CoinChange.js ├── CombinationSum4.java ├── Combinationsum4.js ├── Fibonacci.java ├── Fibonacci.js ├── FriendsPairing.java ├── MinimumCostForTickets.java ├── MinimumCostForTickets.js ├── Notes2.pdf ├── Notes3.pdf ├── Notes4.pdf ├── PerfectSquares.java ├── Triangle.java ├── Triangle.js ├── buyandsellstock3.java ├── buyandsellstocks4.java ├── buyandsellstocks4.js ├── lcs.java ├── lcs.js ├── lis.java ├── lps.java ├── notes1.pdf └── notes5.pdf ├── 7.LinkedList ├── ListNode.java ├── PartitionList.java ├── ll.js ├── notes1.pdf ├── notes2.pdf ├── removeDuplicatedFromSortedxList.java ├── removeDuplicatesFromSortedList.js └── removeNthNodeFromLast.js ├── 8.Stacks ├── .DS_Store ├── AsteroidCollision.java ├── BackspaceStrings.js ├── BuildArrayWithStackOperations.js ├── MaxFrequencyStack.js ├── RemovingStarsFromString.java ├── RemovingStarsFromString.js ├── Stack.js ├── StackusingLL.js ├── notes1.pdf └── notes2.pdf ├── 9.Queues ├── notes.pdf └── queueUsingLL.js └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/.DS_Store -------------------------------------------------------------------------------- /1.Arrays/1.TwoSum/solution.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/two-sum/ 2 | 3 | var twoSum = function(nums, target) { 4 | let n = nums.length; 5 | for(let i = 0; i <= n-2; i++) { 6 | for(let j = i + 1; j < n; j++) { 7 | if(nums[i] + nums[j] == target) { 8 | return [i, j]; 9 | } 10 | } 11 | } 12 | }; -------------------------------------------------------------------------------- /1.Arrays/2.ReverseAString/solution.js: -------------------------------------------------------------------------------- 1 | // https://leetcode.com/problems/reverse-string/ 2 | 3 | /** 4 | * @param {character[]} s 5 | * @return {void} Do not return anything, modify s in-place instead. 6 | */ 7 | var reverseString = function(s) { 8 | let n = s.length; 9 | let i = 0; 10 | let j = n-1; 11 | while(i <= j) { 12 | // swapping the values 13 | let temp = s[i]; 14 | s[i] = s[j]; 15 | s[j] = temp; 16 | 17 | // move to the next positions 18 | i++; 19 | j--; 20 | } 21 | }; -------------------------------------------------------------------------------- /1.Arrays/3.TwoSum2InputIsSorted/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/ 3 | * @param {number[]} numbers 4 | * @param {number} target 5 | * @return {number[]} 6 | */ 7 | var twoSum = function(nums, target) { 8 | let n = nums.length; 9 | let i = 0; 10 | let j = n-1; 11 | while(i < j) { 12 | if(nums[i] + nums[j] == target) { 13 | return [i+1, j+1]; // 0index -> 1index 14 | } 15 | else if(nums[i] + nums[j] > target) { 16 | j--; 17 | } else { 18 | i++; 19 | } 20 | } 21 | }; -------------------------------------------------------------------------------- /1.Arrays/4.SquareOfSortedArray/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | * https://leetcode.com/problems/squares-of-a-sorted-array/description/ 5 | */ 6 | var sortedSquares = function(nums) { 7 | let n = nums.length; 8 | let result = Array(n); // new empty array of length n 9 | let left = 0, right = n-1; 10 | for(let i = n-1; i >= 0; i--) { 11 | if(nums[left]**2 < nums[right]**2) { 12 | result[i] = nums[right]**2; 13 | right--; 14 | } else { 15 | result[i] = nums[left]**2; 16 | left++; 17 | } 18 | } 19 | return result; 20 | }; -------------------------------------------------------------------------------- /1.Arrays/Notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/1.Arrays/Notes1.pdf -------------------------------------------------------------------------------- /1.Arrays/Notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/1.Arrays/Notes2.pdf -------------------------------------------------------------------------------- /1.Arrays/sortfunctiondemo.js: -------------------------------------------------------------------------------- 1 | let arr = [3,4,1,5,10,9]; 2 | 3 | /** 4 | * if the callback of sort function returns a negative value 5 | * - the first argument is put first and then the second argument 6 | * else if the callback of the sort function returns a positive value 7 | * - the second argument is put first and then the first argument 8 | * 9 | */ 10 | 11 | 12 | /** 13 | * 14 | * x = 4 15 | * y = 5 16 | * (x, y) => x - y 17 | * 4 - 5 -> -ve 18 | * 19 | * [4, 5] 20 | * 21 | * 22 | * x = 7 23 | * y = 3 24 | * (x, y) => x - y 25 | * 7 - 3 -> +ve 26 | * 27 | * [3, 7] 28 | */ 29 | 30 | arr.sort((x, y) => x - y); // increasing 31 | 32 | 33 | console.log(arr); 34 | 35 | /** 36 | * 37 | * x = 4 38 | * y = 5 39 | * (x, y) => y - x 40 | * 5 - 4 -> +ve 41 | * 42 | * [5, 4] 43 | * 44 | * 45 | * x = 7 46 | * y = 3 47 | * (x, y) => y - x 48 | * 3 - 7 -> -ve 49 | * 50 | * [7, 3] 51 | */ 52 | arr.sort((x, y) => y - x); // decreasing 53 | 54 | console.log(arr); -------------------------------------------------------------------------------- /10.Deque/Dll.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.next = null; 5 | this.prev = null; 6 | } 7 | } 8 | 9 | class DoublyLinkedList { 10 | constructor() { 11 | this.head = null; 12 | this.tail = null; 13 | } 14 | 15 | isEmpty() { 16 | return this.head == null; 17 | } 18 | 19 | addAtHead(data) { 20 | // 1. Is the ll is empty, create a new node and assign it as head and tail both 21 | if(this.isEmpty()) { 22 | // a. Create a new node 23 | const newNode = new Node(data); 24 | // b. Assign this node as the head 25 | this.head = newNode; 26 | // c. Assign the same node as tail 27 | this.tail = newNode; 28 | } else { 29 | // 2. If the list is not empty, then create a new node and attach it behind the old head 30 | 31 | // a. Create a new node 32 | const newNode = new Node(data); 33 | // b. attach behind the old head by making next of newNode equal to old head 34 | newNode.next = this.head; 35 | // c. Connect the prev of the old head to the newNode 36 | this.head.prev = newNode; 37 | // d. Make the newNode as the new head of the list 38 | this.head = newNode; 39 | } 40 | } 41 | 42 | addAtTail(data) { 43 | if(this.isEmpty()) { 44 | // 1. If the LL is empty then adding at head is same as adding at tail 45 | this.addAtHead(data); 46 | } else { 47 | // 2. LL is not empty 48 | 49 | // a. Create a new node 50 | const newNode = new Node(data); 51 | // b. Setup the conn 52 | this.tail.next = newNode; 53 | newNode.prev = this.tail; 54 | // c. reassign the tail as the new node 55 | this.tail = newNode; 56 | } 57 | } 58 | 59 | removeAtHead() { 60 | if(this.isEmpty()) { 61 | // 1. If the ll is empty , we can't do anything 62 | return; 63 | } else if (this.head.next == null) { 64 | // 2. You have a single node, just destroy the node 65 | this.head = null; 66 | this.tail = null; 67 | } else { 68 | // 3. LL has size more than 1 69 | 70 | // a. Remember the new incmoing head 71 | const newHead = this.head.next; 72 | // b. break the conn 73 | this.head.next = null; 74 | newHead.prev = null; 75 | // c. assign the new head as the head 76 | this.head = newHead; 77 | 78 | } 79 | } 80 | 81 | removeAtTail() { 82 | if(this.isEmpty()) { 83 | // 1. If the ll is empty, we can't do anything 84 | return; 85 | } else if(this.head.next == null) { 86 | // 2. If LL is of size 1, then remove the single node 87 | this.head = null; 88 | this.tail = null; 89 | } else { 90 | // 3. LL with more than 1 size 91 | 92 | // a. remember the newTail 93 | const newTail = this.tail.prev; 94 | // b. break the conn 95 | newTail.next = null; 96 | this.tail.prev = null; 97 | // c. reassign the tail 98 | this.tail = newTail; 99 | } 100 | } 101 | 102 | removeNode(node) { 103 | if(node.prev == null) { 104 | // 1. If the node is a head node call removeAtHead 105 | this.removeAtHead(); 106 | } else if(node.next == null) { 107 | // 2. If the node is a tail node call removeAtTail 108 | this.removeAtTail(); 109 | } else { 110 | // 3. Some node in between 111 | const prevNode = node.prev; 112 | const nextNode = node.next; 113 | // prevnode - node - nextNode 114 | // a. Break conn between prevNode and currNode 115 | prevNode.next = null; 116 | node.prev = null; 117 | 118 | // b. break the conn between nextnode and currnode 119 | nextNode.prev = null; 120 | node.next = null; 121 | 122 | // c. Connect the prev node with nextNode 123 | prevNode.next = nextNode; 124 | nextNode.prev = prevNode; 125 | } 126 | } 127 | 128 | display() { 129 | // head to tail 130 | let temp = this.head; 131 | while(temp != null) { 132 | console.log(temp.data); 133 | temp = temp.next; 134 | } 135 | 136 | console.log("*******"); 137 | 138 | // tail to head 139 | 140 | temp = this.tail; 141 | while(temp != null) { 142 | console.log(temp.data); 143 | temp = temp.prev; 144 | } 145 | } 146 | 147 | } 148 | 149 | const dll = new DoublyLinkedList(); 150 | dll.addAtHead(10); 151 | dll.addAtHead(9); 152 | dll.addAtHead(8); 153 | dll.addAtTail(11); 154 | dll.addAtTail(12); 155 | dll.removeAtHead(); 156 | dll.removeAtTail(); 157 | dll.removeAtHead(); 158 | dll.removeAtTail(); 159 | dll.removeAtHead(); 160 | dll.removeAtTail(); 161 | // 8 - 9 - 10 - 11 - 12 162 | dll.display(); -------------------------------------------------------------------------------- /10.Deque/deque.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.next = null; 5 | this.prev = null; 6 | } 7 | } 8 | 9 | class DoublyLinkedList { 10 | constructor() { 11 | this.head = null; 12 | this.tail = null; 13 | } 14 | 15 | isEmpty() { 16 | return this.head == null; 17 | } 18 | 19 | addAtHead(data) { 20 | // 1. Is the ll is empty, create a new node and assign it as head and tail both 21 | if(this.isEmpty()) { 22 | // a. Create a new node 23 | const newNode = new Node(data); 24 | // b. Assign this node as the head 25 | this.head = newNode; 26 | // c. Assign the same node as tail 27 | this.tail = newNode; 28 | } else { 29 | // 2. If the list is not empty, then create a new node and attach it behind the old head 30 | 31 | // a. Create a new node 32 | const newNode = new Node(data); 33 | // b. attach behind the old head by making next of newNode equal to old head 34 | newNode.next = this.head; 35 | // c. Connect the prev of the old head to the newNode 36 | this.head.prev = newNode; 37 | // d. Make the newNode as the new head of the list 38 | this.head = newNode; 39 | } 40 | } 41 | 42 | addAtTail(data) { 43 | if(this.isEmpty()) { 44 | // 1. If the LL is empty then adding at head is same as adding at tail 45 | this.addAtHead(data); 46 | } else { 47 | // 2. LL is not empty 48 | 49 | // a. Create a new node 50 | const newNode = new Node(data); 51 | // b. Setup the conn 52 | this.tail.next = newNode; 53 | newNode.prev = this.tail; 54 | // c. reassign the tail as the new node 55 | this.tail = newNode; 56 | } 57 | } 58 | 59 | removeAtHead() { 60 | if(this.isEmpty()) { 61 | // 1. If the ll is empty , we can't do anything 62 | return; 63 | } else if (this.head.next == null) { 64 | // 2. You have a single node, just destroy the node 65 | this.head = null; 66 | this.tail = null; 67 | } else { 68 | // 3. LL has size more than 1 69 | 70 | // a. Remember the new incmoing head 71 | const newHead = this.head.next; 72 | // b. break the conn 73 | this.head.next = null; 74 | newHead.prev = null; 75 | // c. assign the new head as the head 76 | this.head = newHead; 77 | 78 | } 79 | } 80 | 81 | removeAtTail() { 82 | if(this.isEmpty()) { 83 | // 1. If the ll is empty, we can't do anything 84 | return; 85 | } else if(this.head.next == null) { 86 | // 2. If LL is of size 1, then remove the single node 87 | this.head = null; 88 | this.tail = null; 89 | } else { 90 | // 3. LL with more than 1 size 91 | 92 | // a. remember the newTail 93 | const newTail = this.tail.prev; 94 | // b. break the conn 95 | newTail.next = null; 96 | this.tail.prev = null; 97 | // c. reassign the tail 98 | this.tail = newTail; 99 | } 100 | } 101 | 102 | display() { 103 | // head to tail 104 | let temp = this.head; 105 | while(temp != null) { 106 | console.log(temp.data); 107 | temp = temp.next; 108 | } 109 | 110 | console.log("*******"); 111 | 112 | // tail to head 113 | 114 | temp = this.tail; 115 | while(temp != null) { 116 | console.log(temp.data); 117 | temp = temp.prev; 118 | } 119 | } 120 | 121 | } 122 | 123 | class Deque { 124 | constructor() { 125 | this.dll = new DoublyLinkedList(); 126 | } 127 | 128 | addAtFront(data) { 129 | this.dll.addAtHead(data); 130 | } 131 | 132 | addAtBack(data) { 133 | this.dll.addAtTail(data); 134 | } 135 | 136 | removeAtFront() { 137 | this.dll.removeAtHead(); 138 | } 139 | 140 | removeAtBack() { 141 | this.dll.removeAtTail(); 142 | } 143 | 144 | getBack() { 145 | if(this.dll.tail) 146 | return this.dll.tail.data; 147 | } 148 | 149 | getFront() { 150 | if(this.dll.head) 151 | return this.dll.head.data; 152 | } 153 | } -------------------------------------------------------------------------------- /10.Deque/lrucache.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(key, value) { 3 | this.data = key; 4 | this.value = value; 5 | this.next = null; 6 | this.prev = null; 7 | } 8 | } 9 | 10 | class DoublyLinkedList { 11 | constructor() { 12 | this.head = null; 13 | this.tail = null; 14 | } 15 | 16 | isEmpty() { 17 | return this.head == null; 18 | } 19 | 20 | addAtHead(key, value) { 21 | // 1. Is the ll is empty, create a new node and assign it as head and tail both 22 | if(this.isEmpty()) { 23 | // a. Create a new node 24 | const newNode = new Node(key, value); 25 | // b. Assign this node as the head 26 | this.head = newNode; 27 | // c. Assign the same node as tail 28 | this.tail = newNode; 29 | return newNode; 30 | } else { 31 | // 2. If the list is not empty, then create a new node and attach it behind the old head 32 | 33 | // a. Create a new node 34 | const newNode = new Node(key, value); 35 | // b. attach behind the old head by making next of newNode equal to old head 36 | newNode.next = this.head; 37 | // c. Connect the prev of the old head to the newNode 38 | this.head.prev = newNode; 39 | // d. Make the newNode as the new head of the list 40 | this.head = newNode; 41 | return newNode; 42 | } 43 | } 44 | 45 | addAtTail(key, value) { 46 | if(this.isEmpty()) { 47 | // 1. If the LL is empty then adding at head is same as adding at tail 48 | this.addAtHead(key, value); 49 | } else { 50 | // 2. LL is not empty 51 | 52 | // a. Create a new node 53 | const newNode = new Node(key, value); 54 | // b. Setup the conn 55 | this.tail.next = newNode; 56 | newNode.prev = this.tail; 57 | // c. reassign the tail as the new node 58 | this.tail = newNode; 59 | } 60 | } 61 | 62 | removeAtHead() { 63 | if(this.isEmpty()) { 64 | // 1. If the ll is empty , we can't do anything 65 | return; 66 | } else if (this.head.next == null) { 67 | // 2. You have a single node, just destroy the node 68 | this.head = null; 69 | this.tail = null; 70 | } else { 71 | // 3. LL has size more than 1 72 | 73 | // a. Remember the new incmoing head 74 | const newHead = this.head.next; 75 | // b. break the conn 76 | this.head.next = null; 77 | newHead.prev = null; 78 | // c. assign the new head as the head 79 | this.head = newHead; 80 | 81 | } 82 | } 83 | 84 | removeAtTail() { 85 | if(this.isEmpty()) { 86 | // 1. If the ll is empty, we can't do anything 87 | return; 88 | } else if(this.head.next == null) { 89 | // 2. If LL is of size 1, then remove the single node 90 | this.head = null; 91 | this.tail = null; 92 | } else { 93 | // 3. LL with more than 1 size 94 | 95 | // a. remember the newTail 96 | const newTail = this.tail.prev; 97 | // b. break the conn 98 | newTail.next = null; 99 | this.tail.prev = null; 100 | // c. reassign the tail 101 | this.tail = newTail; 102 | } 103 | } 104 | 105 | removeNode(node) { 106 | if(node.prev == null) { 107 | // 1. If the node is a head node call removeAtHead 108 | this.removeAtHead(); 109 | } else if(node.next == null) { 110 | // 2. If the node is a tail node call removeAtTail 111 | this.removeAtTail(); 112 | } else { 113 | // 3. Some node in between 114 | const prevNode = node.prev; 115 | const nextNode = node.next; 116 | // prevnode - node - nextNode 117 | // a. Break conn between prevNode and currNode 118 | prevNode.next = null; 119 | node.prev = null; 120 | 121 | // b. break the conn between nextnode and currnode 122 | nextNode.prev = null; 123 | node.next = null; 124 | 125 | // c. Connect the prev node with nextNode 126 | prevNode.next = nextNode; 127 | nextNode.prev = prevNode; 128 | } 129 | } 130 | 131 | display() { 132 | // head to tail 133 | let temp = this.head; 134 | while(temp != null) { 135 | console.log(temp.data); 136 | temp = temp.next; 137 | } 138 | 139 | console.log("*******"); 140 | 141 | // tail to head 142 | 143 | temp = this.tail; 144 | while(temp != null) { 145 | console.log(temp.data); 146 | temp = temp.prev; 147 | } 148 | } 149 | 150 | } 151 | 152 | 153 | /** 154 | * @param {number} capacity 155 | */ 156 | var LRUCache = function(capacity) { 157 | this.dll = new DoublyLinkedList(); 158 | this.cacheCapacity = capacity; 159 | this.size = 0; // current cache size 160 | this.mp = {}; 161 | }; 162 | 163 | /** 164 | * @param {number} key 165 | * @return {number} 166 | */ 167 | LRUCache.prototype.get = function(key) { 168 | if(this.mp[key] == undefined) return -1; 169 | const result = this.mp[key].value; 170 | const nodeTobeRemoved = this.mp[key]; 171 | this.dll.removeNode(nodeTobeRemoved); 172 | this.mp[key] = this.dll.addAtHead(key, result); 173 | return result; 174 | }; 175 | 176 | /** 177 | * @param {number} key 178 | * @param {number} value 179 | * @return {void} 180 | */ 181 | LRUCache.prototype.put = function(key, value) { 182 | if(this.mp[key] != undefined) { 183 | // the key we wanted to add already exist 184 | const nodeTobeRemoved = this.mp[key]; 185 | this.dll.removeNode(nodeTobeRemoved); 186 | this.mp[key] = this.dll.addAtHead(key, value); 187 | } else { 188 | // a new key value pair is being added 189 | if(this.size == this.cacheCapacity) { 190 | // the cache is full 191 | // remove the lru element 192 | delete this.mp[this.dll.tail.data]; 193 | this.dll.removeAtTail(); 194 | this.size--; 195 | } 196 | this.mp[key] = this.dll.addAtHead(key, value); 197 | this.size++; 198 | } 199 | }; 200 | 201 | /** 202 | * Your LRUCache object will be instantiated and called as such: 203 | * var obj = new LRUCache(capacity) 204 | * var param_1 = obj.get(key) 205 | * obj.put(key,value) 206 | */ -------------------------------------------------------------------------------- /10.Deque/maximumSlidingWindowOfSizeK.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number[]} 5 | */ 6 | class Node { 7 | constructor(data) { 8 | this.data = data; 9 | this.next = null; 10 | this.prev = null; 11 | } 12 | } 13 | 14 | class DoublyLinkedList { 15 | constructor() { 16 | this.head = null; 17 | this.tail = null; 18 | } 19 | 20 | isEmpty() { 21 | return this.head == null; 22 | } 23 | 24 | addAtHead(data) { 25 | // 1. Is the ll is empty, create a new node and assign it as head and tail both 26 | if(this.isEmpty()) { 27 | // a. Create a new node 28 | const newNode = new Node(data); 29 | // b. Assign this node as the head 30 | this.head = newNode; 31 | // c. Assign the same node as tail 32 | this.tail = newNode; 33 | } else { 34 | // 2. If the list is not empty, then create a new node and attach it behind the old head 35 | 36 | // a. Create a new node 37 | const newNode = new Node(data); 38 | // b. attach behind the old head by making next of newNode equal to old head 39 | newNode.next = this.head; 40 | // c. Connect the prev of the old head to the newNode 41 | this.head.prev = newNode; 42 | // d. Make the newNode as the new head of the list 43 | this.head = newNode; 44 | } 45 | } 46 | 47 | addAtTail(data) { 48 | if(this.isEmpty()) { 49 | // 1. If the LL is empty then adding at head is same as adding at tail 50 | this.addAtHead(data); 51 | } else { 52 | // 2. LL is not empty 53 | 54 | // a. Create a new node 55 | const newNode = new Node(data); 56 | // b. Setup the conn 57 | this.tail.next = newNode; 58 | newNode.prev = this.tail; 59 | // c. reassign the tail as the new node 60 | this.tail = newNode; 61 | } 62 | } 63 | 64 | removeAtHead() { 65 | if(this.isEmpty()) { 66 | // 1. If the ll is empty , we can't do anything 67 | return; 68 | } else if (this.head.next == null) { 69 | // 2. You have a single node, just destroy the node 70 | this.head = null; 71 | this.tail = null; 72 | } else { 73 | // 3. LL has size more than 1 74 | 75 | // a. Remember the new incmoing head 76 | const newHead = this.head.next; 77 | // b. break the conn 78 | this.head.next = null; 79 | newHead.prev = null; 80 | // c. assign the new head as the head 81 | this.head = newHead; 82 | 83 | } 84 | } 85 | 86 | removeAtTail() { 87 | if(this.isEmpty()) { 88 | // 1. If the ll is empty, we can't do anything 89 | return; 90 | } else if(this.head.next == null) { 91 | // 2. If LL is of size 1, then remove the single node 92 | this.head = null; 93 | this.tail = null; 94 | } else { 95 | // 3. LL with more than 1 size 96 | 97 | // a. remember the newTail 98 | const newTail = this.tail.prev; 99 | // b. break the conn 100 | newTail.next = null; 101 | this.tail.prev = null; 102 | // c. reassign the tail 103 | this.tail = newTail; 104 | } 105 | } 106 | 107 | display() { 108 | // head to tail 109 | let temp = this.head; 110 | while(temp != null) { 111 | console.log(temp.data); 112 | temp = temp.next; 113 | } 114 | 115 | console.log("*******"); 116 | 117 | // tail to head 118 | 119 | temp = this.tail; 120 | while(temp != null) { 121 | console.log(temp.data); 122 | temp = temp.prev; 123 | } 124 | } 125 | 126 | } 127 | 128 | class Deque { 129 | constructor() { 130 | this.dll = new DoublyLinkedList(); 131 | } 132 | 133 | isEmpty() { 134 | return this.dll.isEmpty(); 135 | } 136 | 137 | addAtFront(data) { 138 | this.dll.addAtHead(data); 139 | } 140 | 141 | addAtBack(data) { 142 | this.dll.addAtTail(data); 143 | } 144 | 145 | removeAtFront() { 146 | this.dll.removeAtHead(); 147 | } 148 | 149 | removeAtBack() { 150 | this.dll.removeAtTail(); 151 | } 152 | 153 | getBack() { 154 | if(this.dll.tail) 155 | return this.dll.tail.data; 156 | } 157 | 158 | getFront() { 159 | if(this.dll.head) 160 | return this.dll.head.data; 161 | } 162 | } 163 | var maxSlidingWindow = function(nums, k) { 164 | // Time: O(n) 165 | const dq = new Deque(); // deque of indexes 166 | 167 | const result = []; 168 | 169 | // 1. Prepare the first window of size k 170 | for(let i = 0; i < k; i++) { 171 | if(dq.isEmpty()) { 172 | // if the deque is empty directly add the element 173 | dq.addAtBack(i); 174 | } else { 175 | while(!dq.isEmpty() && nums[i] > nums[dq.getBack()]) { 176 | // till the time the incoming element > element at back of deque 177 | // we will remove the element from back 178 | dq.removeAtBack(); 179 | } 180 | dq.addAtBack(i); 181 | } 182 | } 183 | 184 | result.push(nums[dq.getFront()]); 185 | 186 | for(let i = k; i < nums.length; i++) { 187 | // remove any element that is not in the proximity of the window 188 | while(!dq.isEmpty() && dq.getFront() <= i - k) { 189 | dq.removeAtFront(); 190 | } 191 | // start adding the element 192 | if(dq.isEmpty()) { 193 | dq.addAtBack(i); 194 | } else { 195 | while(!dq.isEmpty() && nums[i] > nums[dq.getBack()]) { 196 | // till the time the incoming element > element at back of deque 197 | // we will remove the element from back 198 | dq.removeAtBack(); 199 | } 200 | dq.addAtBack(i); 201 | } 202 | result.push(nums[dq.getFront()]); 203 | } 204 | return result; 205 | 206 | 207 | }; -------------------------------------------------------------------------------- /10.Deque/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/10.Deque/notes1.pdf -------------------------------------------------------------------------------- /11.BinaryTree/BT.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | } 8 | 9 | class BinaryTree { 10 | constructor() { 11 | this.root = null; 12 | } 13 | } -------------------------------------------------------------------------------- /11.BinaryTree/FlipEquivalent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root1 11 | * @param {TreeNode} root2 12 | * @return {boolean} 13 | */ 14 | 15 | function f(root1, root2) { 16 | if(root1 == null && root2 == null) return true; 17 | 18 | if(root1 == null || root2 == null) { 19 | // one of them is null 20 | return false; 21 | } 22 | if(root1.val != root2.val) { 23 | return false; 24 | } 25 | 26 | return (f(root1.left, root2.left) && f(root1.right, root2.right)) || (f(root1.left, root2.right) && f(root1.right, root2.left)); 27 | } 28 | var flipEquiv = function (root1, root2) { 29 | return f(root1, root2); 30 | }; -------------------------------------------------------------------------------- /11.BinaryTree/MaxWidthOfABt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | var widthOfBinaryTree = function(root) { 14 | let qu = []; 15 | 16 | let ans = 0n; 17 | 18 | let left = BigInt(0); 19 | let right = null; 20 | let last = null; 21 | 22 | qu.push([root, 0n]); 23 | qu.push(null); 24 | 25 | while(qu.length > 0){ 26 | 27 | let element = qu.shift(); 28 | 29 | if(element == null){ 30 | right = BigInt(last[1]); 31 | // ans = Math.max(ans, right - left + 1n); 32 | if(ans < right - left + 1n) { 33 | ans = right - left + 1n; 34 | } 35 | 36 | if(qu.length != 0){ 37 | qu.push(null); 38 | left = BigInt(qu[0][1]); 39 | } 40 | // console.log(left, right,right - left + 1n, ans ) 41 | }else{ 42 | last = element; 43 | 44 | if(element[0].left){ 45 | qu.push([element[0].left, BigInt(element[1] * 2n + 1n)]); 46 | } 47 | 48 | if(element[0].right){ 49 | qu.push([element[0].right, BigInt(element[1] * 2n + 2n)]); 50 | } 51 | } 52 | } 53 | return ans; 54 | }; -------------------------------------------------------------------------------- /11.BinaryTree/balancedBT.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {boolean} 12 | */ 13 | 14 | let ans ; 15 | function f(root) { 16 | if(root == null) return 0; 17 | 18 | let lst = f(root.left); 19 | let rst = f(root.right); 20 | 21 | ans = ans && (Math.abs(lst-rst) <= 1); 22 | 23 | return 1 + Math.max(lst, rst); 24 | } 25 | var isBalanced = function(root) { 26 | ans = true; 27 | f(root); 28 | return ans; 29 | }; -------------------------------------------------------------------------------- /11.BinaryTree/constructStringfromBT.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {string} 12 | */ 13 | 14 | function f(root) { 15 | if(root == null) return ""; 16 | 17 | const left = f(root.left); 18 | const right = f(root.right); 19 | 20 | 21 | if(left == "" && right == "") { 22 | return `${root.val}`; 23 | } else if(left == "") { 24 | return `${root.val}()(${right})`; 25 | } else if(right == "") { 26 | return `${root.val}(${left})`; 27 | } else { 28 | return `${root.val}(${left})(${right})`; 29 | } 30 | } 31 | var tree2str = function(root) { 32 | return f(root); 33 | }; 34 | 35 | // 2(4) -------------------------------------------------------------------------------- /11.BinaryTree/diameterofaBT.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | 14 | let ans ; 15 | function f(root) { 16 | if(root == null) return 0; 17 | 18 | let lst = f(root.left); 19 | let rst = f(root.right); 20 | 21 | ans = Math.max(ans, lst + rst + 1); 22 | 23 | return 1 + Math.max(lst, rst); 24 | } 25 | var diameterOfBinaryTree = function(root) { 26 | ans = -1; 27 | f(root); 28 | return ans-1; 29 | }; 30 | -------------------------------------------------------------------------------- /11.BinaryTree/duplicatesubtrees.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {TreeNode[]} 12 | */ 13 | let mp = {}; 14 | let result = []; 15 | function f(root) { 16 | if(root == null) return '#'; 17 | 18 | const left = f(root.left); 19 | const right = f(root.right); 20 | 21 | const s = "" + root.val + "," + left + "," + right; 22 | if(!mp[s]) { 23 | mp[s] = 1 24 | } else { 25 | if(mp[s] == 1) { 26 | // this is the first time we detected a duplicate 27 | result.push(root); 28 | } 29 | mp[s] += 1; 30 | } 31 | return s; 32 | } 33 | var findDuplicateSubtrees = function(root) { 34 | mp = {}; 35 | result = []; 36 | f(root); 37 | return result; 38 | }; -------------------------------------------------------------------------------- /11.BinaryTree/houseRobber3.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | 14 | let mpTrue; 15 | let mpFalse 16 | 17 | function f(root, isPR) { 18 | if(root == null) return 0; 19 | 20 | 21 | if(isPR && mpTrue.get(root)) { 22 | // if dp has the state stored for (root, true) 23 | return mpTrue.get(root); 24 | } 25 | 26 | if(!isPR && mpFalse.get(root)) { 27 | // if dp has the state stored for (root, false) 28 | return mpFalse.get(root); 29 | } 30 | 31 | if(!isPR) { 32 | // if the parent is not robber 33 | const leave = f(root.left, false) + f(root.right, false); // we can leave curr 34 | const take = root.val + f(root.left, true) + f(root.right, true); // we can rob curr 35 | 36 | const ans = Math.max(leave, take); // we will take the max choice 37 | 38 | mpFalse.set(root, ans); // store (root, false) in dp 39 | 40 | return ans; 41 | } else { 42 | // parent is robbed 43 | const leave = f(root.left, false) + f(root.right, false); // leave the curr 44 | 45 | const ans = leave; 46 | 47 | mpTrue.set(root, ans);// store (root, true) in dp 48 | 49 | return ans; 50 | } 51 | } 52 | 53 | var rob = function(root) { 54 | mpTrue = new Map(); 55 | mpFalse = new Map(); 56 | 57 | return f(root, false); 58 | }; -------------------------------------------------------------------------------- /11.BinaryTree/inorder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | 14 | let result; 15 | function inorder(root) { 16 | if(root == null) return null; 17 | // If the root is not null, that means it has some data 18 | 19 | 20 | // go to the left sub tree recursively 21 | inorder(root.left); 22 | 23 | // process the root 24 | result.push(root.val); 25 | 26 | // go to the right sub tree recursively 27 | inorder(root.right); 28 | } 29 | 30 | 31 | var inorderTraversal = function(root) { 32 | 33 | result = []; 34 | inorder(root); 35 | return result; 36 | }; -------------------------------------------------------------------------------- /11.BinaryTree/invertBinaryTree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {TreeNode} 12 | */ 13 | function f(root) { 14 | if(root == null) return; 15 | // invert the complete tree 16 | 17 | let temp = root.left; 18 | root.left = root.right; 19 | root.right = temp; 20 | 21 | // please go and invert my left sub tree 22 | f(root.left); 23 | 24 | // please go and invert my right subtree 25 | f(root.right); 26 | 27 | 28 | } 29 | var invertTree = function(root) { 30 | f(root); 31 | return root; 32 | }; -------------------------------------------------------------------------------- /11.BinaryTree/levelOrderLevelWise.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.next = null; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor() { 10 | this.head = null; // head of the ll 11 | this.tail = null; // tail of the ll 12 | } 13 | 14 | isEmpty() { 15 | return this.head == null; 16 | } 17 | 18 | getHead() { 19 | if(this.head == null) return undefined; 20 | return this.head.data; 21 | } 22 | 23 | getTail() { 24 | if(this.tail == null) return undefined; 25 | return this.tail.data; 26 | } 27 | 28 | removeAtHead() { 29 | if(this.head == null) return; // ll is empty 30 | const newHead = this.head.next; // we will store the new head 31 | this.head.next = null; // disconnect the old head from the ll 32 | this.head = newHead; // allocating the brand new head 33 | 34 | // if head beconmes null after removal of the node means ll is empty now 35 | if(this.head == null) { 36 | this.tail = null; 37 | } 38 | } 39 | 40 | addAtTail(data) { 41 | if(this.head == null) { 42 | // ll is empty 43 | const newNode = new Node(data); 44 | this.head = newNode; 45 | this.tail = newNode; 46 | return; 47 | } else { 48 | const newNode = new Node(data); 49 | this.tail.next = newNode; // we are attaching the new node after the prev tail 50 | this.tail = newNode; // we updated the tail property 51 | } 52 | } 53 | } 54 | 55 | class CustomQueue { 56 | constructor() { 57 | this.ll = new LinkedList(); // we will create a brand new empty list 58 | } 59 | enqueue(data) { 60 | this.ll.addAtTail(data); 61 | } 62 | 63 | dequeue() { 64 | this.ll.removeAtHead(); 65 | } 66 | 67 | isEmpty() { 68 | return this.ll.isEmpty(); 69 | } 70 | 71 | front() { 72 | return this.ll.getHead(); 73 | } 74 | 75 | back() { 76 | return this.ll.getTail(); 77 | } 78 | } 79 | 80 | 81 | /** 82 | * Definition for a binary tree node. 83 | * function TreeNode(val, left, right) { 84 | * this.val = (val===undefined ? 0 : val) 85 | * this.left = (left===undefined ? null : left) 86 | * this.right = (right===undefined ? null : right) 87 | * } 88 | */ 89 | /** 90 | * @param {TreeNode} root 91 | * @return {number[][]} 92 | */ 93 | var levelOrder = function(root) { 94 | if(root == null) return []; 95 | const qu = new CustomQueue(); 96 | qu.enqueue(root); 97 | qu.enqueue(null); 98 | const result = []; 99 | let levelArray = new Array(); 100 | while(!qu.isEmpty()) { 101 | const curr = qu.front(); 102 | qu.dequeue(); 103 | if(curr == null) { 104 | // this shows end of the last level 105 | if(!qu.isEmpty()) { 106 | // if the queue is not empty then in the queue we have all the elements 107 | // of the next level 108 | 109 | // before we refresh our level array it has data of last level 110 | result.push(levelArray); 111 | 112 | qu.enqueue(null); // we can use this null as a marker of end of current level 113 | levelArray = new Array(); 114 | } else { 115 | // when queue is empty 116 | result.push(levelArray); 117 | } 118 | } else { 119 | levelArray.push(curr.val); 120 | if(curr.left) { 121 | qu.enqueue(curr.left); 122 | } 123 | if(curr.right) { 124 | qu.enqueue(curr.right); 125 | } 126 | } 127 | 128 | } 129 | return result; 130 | 131 | }; 132 | -------------------------------------------------------------------------------- /11.BinaryTree/maximumDepth.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | function f(root) { 14 | if(root == null) { 15 | // empty subtree 16 | return 0; 17 | } 18 | return 1 + Math.max(f(root.left), f(root.right)); 19 | } 20 | var maxDepth = function(root) { 21 | return f(root); 22 | }; -------------------------------------------------------------------------------- /11.BinaryTree/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/11.BinaryTree/notes.pdf -------------------------------------------------------------------------------- /11.BinaryTree/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/11.BinaryTree/notes2.pdf -------------------------------------------------------------------------------- /11.BinaryTree/notes3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/11.BinaryTree/notes3.pdf -------------------------------------------------------------------------------- /11.BinaryTree/notes4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/11.BinaryTree/notes4.pdf -------------------------------------------------------------------------------- /11.BinaryTree/portorder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | let result; 14 | function postorder(root) { 15 | if(root == null) return null; 16 | // If the root is not null, that means it has some data 17 | 18 | // go to the left sub tree recursively 19 | postorder(root.left); 20 | 21 | // go to the right sub tree recursively 22 | postorder(root.right); 23 | 24 | // process the root 25 | result.push(root.val); 26 | } 27 | var postorderTraversal = function(root) { 28 | 29 | result = []; 30 | postorder(root); 31 | return result; 32 | }; -------------------------------------------------------------------------------- /11.BinaryTree/preorder.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | 14 | let result; 15 | function preorder(root) { 16 | if(root == null) return null; 17 | // If th›e root is not null, that means it has some data 18 | // process the root 19 | result.push(root.val); 20 | 21 | // go to the left sub tree recursively 22 | preorder(root.left); 23 | 24 | // go to the right sub tree recursively 25 | preorder(root.right); 26 | } 27 | 28 | 29 | var preorderTraversal = function(root) { 30 | 31 | result = []; 32 | preorder(root); 33 | return result; 34 | }; -------------------------------------------------------------------------------- /11.BinaryTree/sumroottoleaf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | let ans; 14 | function f(root,num) { 15 | if(root.left == null && root.right == null) { 16 | ans += (10*num + root.val); 17 | return; 18 | } 19 | let n = 10*num + root.val; 20 | if(root.left) { 21 | f(root.left, n); 22 | } 23 | if(root.right) { 24 | f(root.right, n); 25 | } 26 | } 27 | var sumNumbers = function(root) { 28 | ans = 0; 29 | f(root, 0); 30 | return ans; 31 | }; -------------------------------------------------------------------------------- /12.BST/insertInABST.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {number} val 12 | * @return {TreeNode} 13 | */ 14 | 15 | function f(root, val) { 16 | 17 | if(root == null) { 18 | return new TreeNode(val); 19 | } 20 | 21 | if(root.val > val) { 22 | // value can only live in the left subtree 23 | root.left = f(root.left, val); 24 | } else { 25 | // value can only live in the right subtree 26 | root.right = f(root.right, val); 27 | } 28 | 29 | return root; 30 | 31 | } 32 | 33 | var insertIntoBST = function(root, val) { 34 | return f(root, val); 35 | }; -------------------------------------------------------------------------------- /12.BST/notes 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/12.BST/notes 2.pdf -------------------------------------------------------------------------------- /12.BST/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/12.BST/notes1.pdf -------------------------------------------------------------------------------- /12.BST/sortedListToBST.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val, left, right) { 11 | * this.val = (val===undefined ? 0 : val) 12 | * this.left = (left===undefined ? null : left) 13 | * this.right = (right===undefined ? null : right) 14 | * } 15 | */ 16 | /** 17 | * @param {ListNode} head 18 | * @return {TreeNode} 19 | */ 20 | function calcMid(head, tail) { 21 | let slow = head; 22 | let fast = head; 23 | while(fast != tail && fast.next != tail) { 24 | slow = slow.next; 25 | fast = fast.next.next; 26 | } 27 | return slow; // midnode 28 | } 29 | function makeBst(head, tail) { 30 | if(head == null) return null; 31 | if(head == tail) return null; 32 | let mid = calcMid(head, tail); 33 | let root = new TreeNode(mid.val) 34 | root.left = makeBst(head, mid) 35 | root.right = makeBst(mid.next, tail); 36 | return root; 37 | 38 | } 39 | var sortedListToBST = function(head) { 40 | return makeBst(head, null); 41 | }; -------------------------------------------------------------------------------- /13.Hashing/HashMap.js: -------------------------------------------------------------------------------- 1 | // 1. Structure that should contain array of linked list 2 | // 2. Load factor , at any point of time load factor > 0.5 we rehash 3 | // Java - Hashmap, C++ - unordered_map , python - dict, js - objects 4 | var Node = function(key, value) { 5 | this.key = key; // key 6 | this.value = value; 7 | this.next = null; // until or unless we attach this new node to a list, the next property should be null 8 | } 9 | 10 | 11 | var MyLinkedList = function() { 12 | this.head = null; // because initially everything is empty 13 | }; 14 | 15 | /** 16 | * @param {number} val 17 | * @return {void} 18 | */ 19 | MyLinkedList.prototype.addAtHead = function(key, val) { 20 | if(this.head == null) { 21 | // means the ll is empty, so this node should become the head 22 | this.head = new Node(key, val); 23 | } else { 24 | // when ll is not. empty 25 | let n = new Node(key, val); 26 | n.next = this.head; 27 | this.head = n; 28 | } 29 | }; 30 | 31 | MyLinkedList.prototype.deleteAtHead = function() { 32 | if(this.head == null) return; 33 | let nextHead = this.head.next; 34 | let nodeToBeDelete = this.head; // curr head 35 | this.head = nextHead; 36 | nodeToBeDelete.next = null; // prev head disconnected 37 | } 38 | 39 | class HashMap { 40 | constructor() { 41 | this.lambdaFactorThreshold = 0.5; // threshold lambda factor 42 | this.lambdaFactorLowerThresold = 0.25; 43 | this.maxSize = 2; // how many buckets are avaialable 44 | 45 | this.arr = Array(this.maxSize); 46 | 47 | for(let i = 0; i < this.maxSize; i++) { 48 | this.arr[i] = new MyLinkedList(); // store empty LL at each index 49 | } 50 | 51 | this.currSize = 0; // how many elements are inserted 52 | } 53 | 54 | hashFunction(key) { 55 | // takes key as a parameter 56 | // apply the hash function on that key 57 | // the result of the hashfunction is the bucket index in the given array 58 | 59 | // Suggest any hashfunction for key as a string???? 60 | 61 | // "mango": 3, 62 | // ((ascii(m)*p^0) + (ascii(a)*p^1) + (ascii(n)*p^2) + (ascii(g)*p^3) .... )%array_size 63 | // "apple": 5 64 | 65 | // (a + b)%c => (a%c + b%c)%c 66 | // (a * b)%c => (a%c * b%c)%c 67 | 68 | let ans = 0; // This variable will be the final hashed value 69 | let p = 101; // prime number to keep 70 | let pow = 1; // intially power is p^0 71 | let C = this.maxSize; 72 | for(let i = 0; i < key.length; i++) { 73 | // go to each character of given 74 | let asciiValue = this.ascii(key, i); 75 | // ans = ((ans%this.currSize) + ((asciiValue%this.currSize)*(pow%this.currSize))%this.currSize) % this.currSize; 76 | 77 | ans = ( (ans%C)+ ((asciiValue%C)*(pow%C))%C ) % C; 78 | // for next iteration we will incremement the power 79 | pow = ((pow%C) * p%C)%C; 80 | } 81 | return ans; 82 | /** 83 | * i = 0, p = 101, pow = 1 (101^0) 84 | * i = 1, p = 101, pow = 101^1 85 | * i = 2, p = 101, pow = (101)^2 86 | */ 87 | } 88 | 89 | ascii(key, index) { 90 | return key.charCodeAt(index); 91 | } 92 | 93 | display() { 94 | for(let i = 0; i < this.arr.length; i++) { 95 | let temp = this.arr[i].head; 96 | let str = "LL: "; 97 | while(temp != null) { 98 | str += "(" + temp.key + ", " + temp.value + ") -> "; 99 | temp = temp.next; 100 | } 101 | console.log(str); 102 | } 103 | console.log(this.currSize, this.maxSize); 104 | console.log("*******") 105 | } 106 | 107 | update(key, value) { 108 | // we assume that key is always present 109 | const bucketIndex = this.hashFunction(key); 110 | let temp = this.arr[bucketIndex].head; 111 | while(temp != null) { 112 | if(temp.key === key) { 113 | temp.value = value; 114 | return; 115 | } 116 | temp = temp.next; 117 | } 118 | } 119 | 120 | insert(key, value) { 121 | // TODO: Implement update part 122 | if(this.search(key)) { 123 | // key value pair is already present 124 | 125 | // no need to insert just update\ 126 | this.update(key, value); 127 | return; 128 | } 129 | 130 | let newLoadFactor = (this.currSize + 1) / this.maxSize; 131 | if(newLoadFactor > this.lambdaFactorThreshold) { 132 | // if after insertion of new (key, value) pair the load factor will go beyonf the thresold 133 | // we should first rehash and then insert 134 | this.rehash(); 135 | } 136 | 137 | const bucketIndex = this.hashFunction(key); // hash value generated by the function is the bucket index of the arr only 138 | 139 | this.arr[bucketIndex].addAtHead(key, value); 140 | this.currSize += 1; // new pair added so size of hashmap increases 141 | 142 | } 143 | 144 | remove(key) { 145 | /** 146 | * 1. Check if the key is even present or not ? 147 | * 2. If the key is present, check in which ll bucket it is, using hash function 148 | * 3. Iterate on the LL and remove the node 149 | */ 150 | 151 | const value = this.search(key); 152 | if(!value) { 153 | console.log("Key is not present, nothing to remove"); 154 | return; 155 | } 156 | 157 | const bucketIndex = this.hashFunction(key); 158 | let temp = this.arr[bucketIndex].head; 159 | 160 | if(temp.key === key) { 161 | // head node need to be deleted 162 | this.arr[bucketIndex].deleteAtHead(); 163 | this.currSize -= 1; 164 | const loadFactor = (this.currSize) / this.maxSize; 165 | if(loadFactor <= this.lambdaFactorLowerThresold) { 166 | this.rehash(0.5); 167 | } 168 | return; 169 | } 170 | 171 | while(temp != null) { 172 | // check if the curr node is just behind the node to be deleted ? 173 | if(temp.next != null && temp.next.key === key) { 174 | const nodeToBeDeleted = temp.next; 175 | temp.next = nodeToBeDeleted.next; // attach prev node to next node 176 | nodeToBeDeleted.next = null; // break the conn 177 | this.currSize -= 1; 178 | const loadFactor = (this.currSize) / this.maxSize; 179 | if(loadFactor <= this.lambdaFactorLowerThresold) { 180 | this.rehash(0.5); 181 | } 182 | return; 183 | } 184 | temp = temp.next; 185 | } 186 | 187 | 188 | } 189 | 190 | search(key) { 191 | // Either the key value pair is present or not ? 192 | // If the key value pair is present then we can be sure that there is only one ll in which it will be present 193 | 194 | // Calc Bucket index of the linked list where the pair might be present 195 | 196 | const bucketIndex = this.hashFunction(key); 197 | 198 | let temp = this.arr[bucketIndex].head; 199 | while(temp != null) { 200 | if(temp.key === key) return temp.value; 201 | temp = temp.next; 202 | } 203 | return undefined; 204 | } 205 | 206 | rehash(factor = 2) { 207 | this.maxSize *= factor; // double the capacity of the arr 208 | 209 | const newArr = Array(this.maxSize);// new array with updated capacity 210 | 211 | for(let i = 0; i < this.maxSize; i++) { 212 | newArr[i] = new MyLinkedList(); 213 | } 214 | 215 | const oldArr = this.arr; 216 | 217 | // Iterate on each node of every LL and insert them in the newArr 218 | 219 | for(let i = 0; i < oldArr.length; i++) { 220 | // go to each bucket of old array 221 | // each bucket has a LL 222 | 223 | let temp = oldArr[i].head; 224 | while(temp != null) { 225 | let key = temp.key; 226 | let value = temp.value; 227 | 228 | // calc new bi 229 | const bucketIndex = this.hashFunction(key); 230 | 231 | // insert in the new array 232 | newArr[bucketIndex].addAtHead(key, value); 233 | 234 | temp = temp.next; 235 | } 236 | } 237 | // make this new array as out hashmap array 238 | this.arr = newArr; 239 | } 240 | } 241 | 242 | 243 | const hm = new HashMap(); 244 | 245 | hm.insert("mango", 10); 246 | hm.display(); 247 | hm.insert("banana", 3); 248 | hm.display(); 249 | hm.insert("apple", 4); 250 | hm.display(); 251 | hm.insert("grapes", 14); 252 | hm.display(); 253 | hm.insert("mango", 55); 254 | hm.display() -------------------------------------------------------------------------------- /13.Hashing/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/13.Hashing/notes.pdf -------------------------------------------------------------------------------- /13.Hashing/test.js: -------------------------------------------------------------------------------- 1 | function hashFunction (key) { 2 | let ans = 0; // This variable will be the final hashed value 3 | let p = 101; // prime number to keep 4 | let pow = 1; // intially power is p^0 5 | let C = 32; 6 | for(let i = 0; i < key.length; i++) { 7 | // go to each character of given 8 | let asciiValue = ascii(key, i); 9 | // ans = ((ans%this.currSize) + ((asciiValue%this.currSize)*(pow%this.currSize))%this.currSize) % this.currSize; 10 | 11 | ans = ( (ans%C)+ ((asciiValue%C)*(pow%C))%C ) % C; 12 | // for next iteration we will incremement the power 13 | pow = ((pow%C) * p%C)%C; 14 | } 15 | return ans; 16 | } 17 | 18 | function ascii(key, index) { 19 | return key.charCodeAt(index); 20 | } 21 | 22 | console.log(hashFunction("banana")); -------------------------------------------------------------------------------- /14.Trie/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/14.Trie/notes.pdf -------------------------------------------------------------------------------- /14.Trie/trie.js: -------------------------------------------------------------------------------- 1 | 2 | class Node { 3 | constructor(data) { 4 | this.data = data; 5 | this.isTerminal = false; 6 | this.children = {} 7 | } 8 | } 9 | 10 | var Trie = function() { 11 | this.root = new Node(null); 12 | }; 13 | 14 | /** 15 | * @param {string} word 16 | * @return {void} 17 | */ 18 | Trie.prototype.insert = function(word) { 19 | let curr = this.root; 20 | for(let i = 0; i < word.length; i++) { 21 | let ch = word[i]; 22 | if(curr.children[ch]) { 23 | // if the child is present 24 | curr = curr.children[ch]; 25 | } else { 26 | let n = new Node(ch); 27 | curr.children[ch] = n; 28 | curr = curr.children[ch]; 29 | } 30 | } 31 | // when the loop ends curr is at the node of last char 32 | curr.isTerminal = true; 33 | }; 34 | 35 | /** 36 | * @param {string} word 37 | * @return {boolean} 38 | */ 39 | Trie.prototype.search = function(word) { 40 | let curr = this.root; 41 | for(let i = 0; i < word.length; i++) { 42 | let ch = word[i]; 43 | if(curr.children[ch]) { 44 | curr = curr.children[ch]; 45 | } else { 46 | return false; 47 | } 48 | } 49 | 50 | return curr.isTerminal; 51 | }; 52 | 53 | /** 54 | * @param {string} prefix 55 | * @return {boolean} 56 | */ 57 | Trie.prototype.startsWith = function(word) { 58 | let curr = this.root; 59 | for(let i = 0; i < word.length; i++) { 60 | let ch = word[i]; 61 | if(curr.children[ch]) { 62 | curr = curr.children[ch]; 63 | } else { 64 | return false; 65 | } 66 | } 67 | 68 | return true; 69 | }; 70 | 71 | /** 72 | * Your Trie object will be instantiated and called as such: 73 | * var obj = new Trie() 74 | * obj.insert(word) 75 | * var param_2 = obj.search(word) 76 | * var param_3 = obj.startsWith(prefix) 77 | */ -------------------------------------------------------------------------------- /15. AVL/avl.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.left = null; 5 | this.right = null; 6 | this.height = 1; 7 | } 8 | } 9 | 10 | class AVL { 11 | constructor() { 12 | this.root = null; 13 | } 14 | 15 | rightRotate(alpha) { 16 | // alpha is the unbalanced node 17 | let beta = alpha.left; 18 | let sigma = beta.right; 19 | beta.right = alpha; 20 | alpha.left = sigma; 21 | 22 | // update heights of alpha and beta 23 | // Update height of alpha first, because height of beta depends on it 24 | alpha.height = Math.max(this.height(alpha.left), this.height(alpha.right)) + 1; 25 | beta.height = Math.max(this.height(beta.left), this.height(beta.right)) + 1; 26 | 27 | // return the new root beta 28 | return beta; 29 | } 30 | 31 | leftRotate(alpha) { 32 | // alpha is the unbalanced node 33 | let beta = alpha.right; 34 | let sigma = beta.left; 35 | beta.left = alpha; 36 | alpha.right = sigma; 37 | 38 | // update heights of alpha and beta 39 | // Update height of alpha first, because height of beta depends on it 40 | alpha.height = Math.max(this.height(alpha.left), this.height(alpha.right)) + 1; 41 | beta.height = Math.max(this.height(beta.left), this.height(beta.right)) + 1; 42 | // return the new root 43 | return beta; 44 | } 45 | 46 | height(node) { 47 | if(node == null) return 0; 48 | return node.height; 49 | } 50 | 51 | getBF(node) { 52 | if(node == null) return 0; 53 | return this.height(node.left) - this.height(node.right); 54 | } 55 | 56 | insertInAVL(data) { 57 | this.root = this.insert(this.root, data); 58 | } 59 | 60 | insert(alpha, data) { 61 | if(alpha == null) return new Node(data); 62 | 63 | // if alpha is not null, you're on an existing node 64 | // now decide whether this data should be inserted in lst or rst of the current node 65 | if(alpha.data > data) { 66 | // go lst 67 | alpha.left = this.insert(alpha.left, data); 68 | } else if(alpha.data < data) { 69 | // go rst 70 | alpha.right = this.insert(alpha.right, data); 71 | } else { 72 | // duplicates 73 | return alpha; // as the node is already present 74 | } 75 | 76 | // update the heiht as new data has been inserted 77 | alpha.height = Math.max(this.height(alpha.left), this.height(alpha.right)) + 1; 78 | 79 | 80 | // this part is executing while coming back in the recursion 81 | // start balancing 82 | 83 | const bf = this.getBF(alpha); 84 | 85 | // if the bf is greater than 1 or less than -1, we have root unbalanced 86 | if(bf > 1) { 87 | // tree is left heavy 88 | // how to decide if we need to do right rotation or left right rotation 89 | let beta = alpha.left; 90 | if(data < beta.data) { 91 | // right rotation 92 | return this.rightRotate(alpha); 93 | } else { 94 | // left right roation 95 | alpha.left = this.leftRotate(alpha.left); 96 | return this.rightRotate(alpha); 97 | } 98 | } else if(bf < -1) { 99 | // tree is right heavy 100 | // how to deciode if we need to do left roation or right left roation 101 | let beta = alpha.right; 102 | if(data > beta.data) { 103 | // left rotate 104 | return this.leftRotate(alpha); 105 | } else { 106 | // right left rotate 107 | alpha.right = this.rightRotate(alpha.right); 108 | return this.leftRotate(alpha); 109 | } 110 | 111 | } 112 | 113 | return alpha; // bf is already 1, -1 or 0 114 | } 115 | 116 | preorder(root, result) { 117 | if(root == null) return null; 118 | // If th›e root is not null, that means it has some data 119 | // process the root 120 | result.push(root.data); 121 | 122 | // go to the left sub tree recursively 123 | this.preorder(root.left, result); 124 | 125 | // go to the right sub tree recursively 126 | this.preorder(root.right, result); 127 | } 128 | 129 | 130 | preorderTraversal() { 131 | 132 | let result = []; 133 | this.preorder(this.root, result); 134 | return result; 135 | } 136 | 137 | inorder(root, result) { 138 | if(root == null) return null; 139 | // If the root is not null, that means it has some data 140 | 141 | 142 | // go to the left sub tree recursively 143 | this.inorder(root.left, result); 144 | 145 | // process the root 146 | result.push(root.data); 147 | 148 | // go to the right sub tree recursively 149 | this.inorder(root.right, result); 150 | } 151 | 152 | 153 | inorderTraversal() { 154 | 155 | let result = []; 156 | this.inorder(this.root, result); 157 | return result; 158 | }; 159 | 160 | postorder(root, result) { 161 | if(root == null) return null; 162 | // If the root is not null, that means it has some data 163 | 164 | // go to the left sub tree recursively 165 | this.postorder(root.left, result); 166 | 167 | // go to the right sub tree recursively 168 | this.postorder(root.right, result); 169 | 170 | // process the root 171 | result.push(root.data); 172 | } 173 | postorderTraversal() { 174 | 175 | let result = []; 176 | this.postorder(this.root, result); 177 | return result; 178 | } 179 | 180 | levelOrderTraversal() { 181 | return this.levelOrder(this.root); 182 | } 183 | 184 | levelOrder(root) { 185 | if(root == null) return []; 186 | const qu = new CustomQueue(); 187 | qu.enqueue(root); 188 | qu.enqueue(null); 189 | const result = []; 190 | let levelArray = new Array(); 191 | while(!qu.isEmpty()) { 192 | const curr = qu.front(); 193 | qu.dequeue(); 194 | if(curr == null) { 195 | // this shows end of the last level 196 | if(!qu.isEmpty()) { 197 | // if the queue is not empty then in the queue we have all the elements 198 | // of the next level 199 | 200 | // before we refresh our level array it has data of last level 201 | result.push(levelArray); 202 | 203 | qu.enqueue(null); // we can use this null as a marker of end of current level 204 | levelArray = new Array(); 205 | } else { 206 | // when queue is empty 207 | result.push(levelArray); 208 | } 209 | } else { 210 | levelArray.push(curr.data); 211 | if(curr.left) { 212 | qu.enqueue(curr.left); 213 | } 214 | if(curr.right) { 215 | qu.enqueue(curr.right); 216 | } 217 | } 218 | 219 | } 220 | return result; 221 | 222 | }; 223 | 224 | 225 | } 226 | 227 | 228 | class LLNode { 229 | constructor(data) { 230 | this.data = data; 231 | this.next = null; 232 | } 233 | } 234 | 235 | class LinkedList { 236 | constructor() { 237 | this.head = null; // head of the ll 238 | this.tail = null; // tail of the ll 239 | } 240 | 241 | isEmpty() { 242 | return this.head == null; 243 | } 244 | 245 | getHead() { 246 | if(this.head == null) return undefined; 247 | return this.head.data; 248 | } 249 | 250 | getTail() { 251 | if(this.tail == null) return undefined; 252 | return this.tail.data; 253 | } 254 | 255 | removeAtHead() { 256 | if(this.head == null) return; // ll is empty 257 | const newHead = this.head.next; // we will store the new head 258 | this.head.next = null; // disconnect the old head from the ll 259 | this.head = newHead; // allocating the brand new head 260 | 261 | // if head beconmes null after removal of the node means ll is empty now 262 | if(this.head == null) { 263 | this.tail = null; 264 | } 265 | } 266 | 267 | addAtTail(data) { 268 | if(this.head == null) { 269 | // ll is empty 270 | const newNode = new LLNode(data); 271 | this.head = newNode; 272 | this.tail = newNode; 273 | return; 274 | } else { 275 | const newNode = new LLNode(data); 276 | this.tail.next = newNode; // we are attaching the new node after the prev tail 277 | this.tail = newNode; // we updated the tail property 278 | } 279 | } 280 | } 281 | 282 | class CustomQueue { 283 | constructor() { 284 | this.ll = new LinkedList(); // we will create a brand new empty list 285 | } 286 | enqueue(data) { 287 | this.ll.addAtTail(data); 288 | } 289 | 290 | dequeue() { 291 | this.ll.removeAtHead(); 292 | } 293 | 294 | isEmpty() { 295 | return this.ll.isEmpty(); 296 | } 297 | 298 | front() { 299 | return this.ll.getHead(); 300 | } 301 | 302 | back() { 303 | return this.ll.getTail(); 304 | } 305 | } 306 | 307 | const avl = new AVL(); 308 | avl.insertInAVL(1); 309 | avl.insertInAVL(2); 310 | avl.insertInAVL(3); 311 | avl.insertInAVL(4); 312 | avl.insertInAVL(5); 313 | avl.insertInAVL(6); 314 | avl.insertInAVL(8); 315 | avl.insertInAVL(9); 316 | 317 | 318 | const pre = avl.preorderTraversal(); 319 | const post = avl.postorderTraversal(); 320 | const ino = avl.inorderTraversal(); 321 | console.log(pre, post, ino); 322 | console.log(avl.levelOrderTraversal()) 323 | 324 | 325 | -------------------------------------------------------------------------------- /15. AVL/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/15. AVL/notes1.pdf -------------------------------------------------------------------------------- /16.Heaps/GenericHeap.js: -------------------------------------------------------------------------------- 1 | class Heap { 2 | constructor(cmp) { 3 | this.arr = []; 4 | this.cmp = cmp; 5 | } 6 | 7 | upheapify(idx) { 8 | // idx represents the index to start upheapify from 9 | while(idx > 0) { 10 | // till the time idx doesnt reach the root 11 | let pi = Math.floor((idx-1)/2); 12 | if(this.cmp(this.arr[pi] , this.arr[idx])) { 13 | // parent is smaller than current element 14 | 15 | // swap the parent and child 16 | let temp = this.arr[pi]; 17 | this.arr[pi] = this.arr[idx]; 18 | this.arr[idx] = temp; 19 | 20 | 21 | idx = pi; 22 | } else { 23 | // everything is good, we have a heap 24 | break; 25 | } 26 | } 27 | } 28 | 29 | insert(data) { 30 | // 1. Insert this data in your array 31 | this.arr.push(data); 32 | 33 | // 2. upheapify 34 | this.upheapify(this.arr.length - 1); 35 | } 36 | 37 | downheapify(idx) { 38 | while(idx < this.arr.length) { 39 | // 1. Calculate the lc and rc index 40 | let lc = 2*idx + 1; // possible lc index 41 | let rc = 2*idx + 2; // possible rc index 42 | let maxEl = idx; // assume root is the max 43 | if(lc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[lc])) { 44 | // left child exist and is greater also 45 | maxEl = lc; 46 | } 47 | 48 | if(rc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[rc])) { 49 | // right child exist && is greater also 50 | maxEl = rc; 51 | } 52 | 53 | // after the above comparison we klnow the biggest element 54 | if(idx == maxEl) { 55 | // root is still the biggest element, dont go further 56 | break; 57 | } else { 58 | // swap the element of root and maxEl 59 | let temp = this.arr[idx]; 60 | this.arr[idx] = this.arr[maxEl]; 61 | this.arr[maxEl] = temp; 62 | 63 | idx = maxEl; 64 | } 65 | } 66 | 67 | 68 | 69 | } 70 | 71 | remove() { 72 | if(this.arr.length == 0) return; 73 | // remove the highest priority element 74 | 75 | // 1. swap the root with last element 76 | 77 | let temp = this.arr[0]; 78 | this.arr[0] = this.arr[this.arr.length - 1]; 79 | this.arr[this.arr.length - 1] = temp; 80 | 81 | // 2. Remove the last element 82 | this.arr.pop(); 83 | 84 | // 3. downheapify 85 | this.downheapify(0); 86 | 87 | } 88 | 89 | display() { 90 | console.log(this.arr) 91 | } 92 | 93 | get() { 94 | return this.arr[0]; // return the root 95 | } 96 | } 97 | 98 | let hp = new Heap((a, b) => { 99 | return a > b // a< b for max heap, a > b for min heap 100 | }); 101 | hp.insert(9); 102 | hp.insert(19); 103 | hp.insert(2); 104 | hp.insert(39); 105 | hp.insert(29); 106 | hp.insert(12); 107 | hp.insert(-9); 108 | hp.insert(6); 109 | 110 | hp.display(); 111 | /** 112 | * 39 113 | * 29 12 114 | * 9 19 2 -9 115 | * 6 116 | */ 117 | 118 | hp.remove(); 119 | 120 | hp.remove(); 121 | hp.display(); 122 | 123 | /** 124 | * 19 125 | * 9 12 126 | * -9 6 2 127 | * 128 | */ 129 | -------------------------------------------------------------------------------- /16.Heaps/KclosespointtoOrigin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} points 3 | * @param {number} k 4 | * @return {number[][]} 5 | */ 6 | class Heap { 7 | constructor(cmp) { 8 | this.arr = []; 9 | this.cmp = cmp; 10 | } 11 | 12 | upheapify(idx) { 13 | // idx represents the index to start upheapify from 14 | while(idx > 0) { 15 | // till the time idx doesnt reach the root 16 | let pi = Math.floor((idx-1)/2); 17 | if(this.cmp(this.arr[pi] , this.arr[idx])) { 18 | // parent is smaller than current element 19 | 20 | // swap the parent and child 21 | let temp = this.arr[pi]; 22 | this.arr[pi] = this.arr[idx]; 23 | this.arr[idx] = temp; 24 | 25 | 26 | idx = pi; 27 | } else { 28 | // everything is good, we have a heap 29 | break; 30 | } 31 | } 32 | } 33 | 34 | insert(data) { 35 | // 1. Insert this data in your array 36 | this.arr.push(data); 37 | 38 | // 2. upheapify 39 | this.upheapify(this.arr.length - 1); 40 | } 41 | 42 | get() { 43 | return this.arr[0]; // return the root 44 | } 45 | 46 | downheapify(idx) { 47 | while(idx < this.arr.length) { 48 | // 1. Calculate the lc and rc index 49 | let lc = 2*idx + 1; // possible lc index 50 | let rc = 2*idx + 2; // possible rc index 51 | let maxEl = idx; // assume root is the max 52 | if(lc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[lc])) { 53 | // left child exist and is greater also 54 | maxEl = lc; 55 | } 56 | 57 | if(rc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[rc])) { 58 | // right child exist && is greater also 59 | maxEl = rc; 60 | } 61 | 62 | // after the above comparison we klnow the biggest element 63 | if(idx == maxEl) { 64 | // root is still the biggest element, dont go further 65 | break; 66 | } else { 67 | // swap the element of root and maxEl 68 | let temp = this.arr[idx]; 69 | this.arr[idx] = this.arr[maxEl]; 70 | this.arr[maxEl] = temp; 71 | 72 | idx = maxEl; 73 | } 74 | } 75 | 76 | 77 | 78 | } 79 | 80 | remove() { 81 | if(this.arr.length == 0) return; 82 | // remove the highest priority element 83 | 84 | // 1. swap the root with last element 85 | 86 | let temp = this.arr[0]; 87 | this.arr[0] = this.arr[this.arr.length - 1]; 88 | this.arr[this.arr.length - 1] = temp; 89 | 90 | // 2. Remove the last element 91 | this.arr.pop(); 92 | 93 | // 3. downheapify 94 | this.downheapify(0); 95 | 96 | } 97 | 98 | display() { 99 | console.log(this.arr) 100 | } 101 | } 102 | 103 | class Point { 104 | constructor(xi, yi) { 105 | this.x = xi; 106 | this.y = yi; 107 | this.dist = Math.sqrt(xi*xi + yi*yi) // store the euclidean distance from the origin 108 | } 109 | } 110 | 111 | var kClosest = function(points, k) { 112 | const hp = new Heap((pointA, pointB) => { 113 | return pointA.dist > pointB.dist; //min heap 114 | }); 115 | for(let i = 0; i < points.length; i++) { 116 | // Iterate on all the given points 117 | const p = new Point(points[i][0], points[i][1]); // for the current x,y create a point object 118 | hp.insert(p); // insert the point in heap 119 | } 120 | let result = []; // result array 121 | while(k > 0) { 122 | k--; 123 | let val = [hp.get().x, hp.get().y]; // get the x and y coordinate fromroot of heap 124 | result.push(val); // store the point in answer array 125 | hp.remove();// remove the root, so that 2nd closes element can come on root 126 | } 127 | return result; 128 | }; -------------------------------------------------------------------------------- /16.Heaps/heap.js: -------------------------------------------------------------------------------- 1 | class MaxHeap { 2 | constructor() { 3 | this.arr = []; 4 | } 5 | 6 | upheapify(idx) { 7 | // idx represents the index to start upheapify from 8 | while(idx > 0) { 9 | // till the time idx doesnt reach the root 10 | let pi = Math.floor((idx-1)/2); 11 | if(this.arr[pi] < this.arr[idx]) { 12 | // parent is smaller than current element 13 | 14 | // swap the parent and child 15 | let temp = this.arr[pi]; 16 | this.arr[pi] = this.arr[idx]; 17 | this.arr[idx] = temp; 18 | 19 | 20 | idx = pi; 21 | } else { 22 | // everything is good, we have a heap 23 | break; 24 | } 25 | } 26 | } 27 | 28 | insert(data) { 29 | // 1. Insert this data in your array 30 | this.arr.push(data); 31 | 32 | // 2. upheapify 33 | this.upheapify(this.arr.length - 1); 34 | } 35 | 36 | downheapify(idx) { 37 | while(idx < this.arr.length) { 38 | // 1. Calculate the lc and rc index 39 | let lc = 2*idx + 1; // possible lc index 40 | let rc = 2*idx + 2; // possible rc index 41 | let maxEl = idx; // assume root is the max 42 | if(lc < this.arr.length && this.arr[maxEl] < this.arr[lc]) { 43 | // left child exist and is greater also 44 | maxEl = lc; 45 | } 46 | 47 | if(rc < this.arr.length && this.arr[maxEl] < this.arr[rc]) { 48 | // right child exist && is greater also 49 | maxEl = rc; 50 | } 51 | 52 | // after the above comparison we klnow the biggest element 53 | if(idx == maxEl) { 54 | // root is still the biggest element, dont go further 55 | break; 56 | } else { 57 | // swap the element of root and maxEl 58 | let temp = this.arr[idx]; 59 | this.arr[idx] = this.arr[maxEl]; 60 | this.arr[maxEl] = temp; 61 | 62 | idx = maxEl; 63 | } 64 | } 65 | 66 | 67 | 68 | } 69 | 70 | remove() { 71 | if(this.arr.length == 0) return; 72 | // remove the highest priority element 73 | 74 | // 1. swap the root with last element 75 | 76 | let temp = this.arr[0]; 77 | this.arr[0] = this.arr[this.arr.length - 1]; 78 | this.arr[this.arr.length - 1] = temp; 79 | 80 | // 2. Remove the last element 81 | this.arr.pop(); 82 | 83 | // 3. downheapify 84 | this.downheapify(0); 85 | 86 | } 87 | 88 | display() { 89 | console.log(this.arr) 90 | } 91 | } 92 | 93 | let hp = new MaxHeap(); 94 | hp.insert(3); 95 | hp.insert(2); 96 | hp.insert(1); 97 | hp.insert(5); 98 | hp.insert(6); 99 | hp.insert(4) 100 | 101 | hp.display(); 102 | /** 103 | * 39 104 | * 29 12 105 | * 9 19 2 -9 106 | * 6 107 | */ 108 | 109 | hp.remove(); 110 | 111 | hp.display(); 112 | 113 | /** 114 | * 19 115 | * 9 12 116 | * -9 6 2 117 | * 118 | */ 119 | -------------------------------------------------------------------------------- /16.Heaps/kthsmallestperimefraction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} arr 3 | * @param {number} k 4 | * @return {number[]} 5 | */ 6 | class Heap { 7 | constructor(cmp) { 8 | this.arr = []; 9 | this.cmp = cmp; 10 | } 11 | 12 | upheapify(idx) { 13 | // idx represents the index to start upheapify from 14 | while(idx > 0) { 15 | // till the time idx doesnt reach the root 16 | let pi = Math.floor((idx-1)/2); 17 | if(this.cmp(this.arr[pi] , this.arr[idx])) { 18 | // parent is smaller than current element 19 | 20 | // swap the parent and child 21 | let temp = this.arr[pi]; 22 | this.arr[pi] = this.arr[idx]; 23 | this.arr[idx] = temp; 24 | 25 | 26 | idx = pi; 27 | } else { 28 | // everything is good, we have a heap 29 | break; 30 | } 31 | } 32 | } 33 | 34 | insert(data) { 35 | // 1. Insert this data in your array 36 | this.arr.push(data); 37 | 38 | // 2. upheapify 39 | this.upheapify(this.arr.length - 1); 40 | } 41 | 42 | downheapify(idx) { 43 | while(idx < this.arr.length) { 44 | // 1. Calculate the lc and rc index 45 | let lc = 2*idx + 1; // possible lc index 46 | let rc = 2*idx + 2; // possible rc index 47 | let maxEl = idx; // assume root is the max 48 | if(lc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[lc])) { 49 | // left child exist and is greater also 50 | maxEl = lc; 51 | } 52 | 53 | if(rc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[rc])) { 54 | // right child exist && is greater also 55 | maxEl = rc; 56 | } 57 | 58 | // after the above comparison we klnow the biggest element 59 | if(idx == maxEl) { 60 | // root is still the biggest element, dont go further 61 | break; 62 | } else { 63 | // swap the element of root and maxEl 64 | let temp = this.arr[idx]; 65 | this.arr[idx] = this.arr[maxEl]; 66 | this.arr[maxEl] = temp; 67 | 68 | idx = maxEl; 69 | } 70 | } 71 | 72 | 73 | 74 | } 75 | 76 | remove() { 77 | if(this.arr.length == 0) return; 78 | // remove the highest priority element 79 | 80 | // 1. swap the root with last element 81 | 82 | let temp = this.arr[0]; 83 | this.arr[0] = this.arr[this.arr.length - 1]; 84 | this.arr[this.arr.length - 1] = temp; 85 | 86 | // 2. Remove thge last element 87 | this.arr.pop(); 88 | 89 | // 3. downheapify 90 | this.downheapify(0); 91 | 92 | } 93 | 94 | display() { 95 | console.log(this.arr) 96 | } 97 | 98 | get() { 99 | return this.arr[0]; // return the root 100 | } 101 | } 102 | 103 | 104 | 105 | class Trip { 106 | constructor( n, d, v) { 107 | this.n = n; // numerator index 108 | this.d = d; // denominator index 109 | this.v = v // value of fraction 110 | } 111 | } 112 | var kthSmallestPrimeFraction = function(arr, k) { 113 | let n = arr.length; 114 | const hp = new Heap((t1, t2) => { 115 | return t1.v > t2.v; //min heap based on v 116 | }) 117 | for(let i = 0; i < n; i++) { 118 | hp.insert(new Trip(0, i, arr[0] / arr[i])); 119 | } 120 | for(let i = 0; i < k-1; i++) { 121 | const el = hp.get(); 122 | hp.remove(); 123 | if(el.n < arr.length - 1) 124 | hp.insert(new Trip(el.n+1, el.d, arr[el.n+1]/arr[el.d])); 125 | } 126 | return [arr[hp.get().n], arr[hp.get().d]]; 127 | }; -------------------------------------------------------------------------------- /16.Heaps/mergeksorteslists.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode[]} lists 10 | * @return {ListNode} 11 | */ 12 | class Heap { 13 | constructor(cmp) { 14 | this.arr = []; 15 | this.cmp = cmp; 16 | } 17 | 18 | upheapify(idx) { 19 | // idx represents the index to start upheapify from 20 | while(idx > 0) { 21 | // till the time idx doesnt reach the root 22 | let pi = Math.floor((idx-1)/2); 23 | if(this.cmp(this.arr[pi] , this.arr[idx])) { 24 | // parent is smaller than current element 25 | 26 | // swap the parent and child 27 | let temp = this.arr[pi]; 28 | this.arr[pi] = this.arr[idx]; 29 | this.arr[idx] = temp; 30 | 31 | 32 | idx = pi; 33 | } else { 34 | // everything is good, we have a heap 35 | break; 36 | } 37 | } 38 | } 39 | 40 | insert(data) { 41 | // 1. Insert this data in your array 42 | this.arr.push(data); 43 | 44 | // 2. upheapify 45 | this.upheapify(this.arr.length - 1); 46 | } 47 | 48 | isEmpty() { 49 | return this.arr.length == 0; 50 | } 51 | 52 | downheapify(idx) { 53 | while(idx < this.arr.length) { 54 | // 1. Calculate the lc and rc index 55 | let lc = 2*idx + 1; // possible lc index 56 | let rc = 2*idx + 2; // possible rc index 57 | let maxEl = idx; // assume root is the max 58 | if(lc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[lc])) { 59 | // left child exist and is greater also 60 | maxEl = lc; 61 | } 62 | 63 | if(rc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[rc])) { 64 | // right child exist && is greater also 65 | maxEl = rc; 66 | } 67 | 68 | // after the above comparison we klnow the biggest element 69 | if(idx == maxEl) { 70 | // root is still the biggest element, dont go further 71 | break; 72 | } else { 73 | // swap the element of root and maxEl 74 | let temp = this.arr[idx]; 75 | this.arr[idx] = this.arr[maxEl]; 76 | this.arr[maxEl] = temp; 77 | 78 | idx = maxEl; 79 | } 80 | } 81 | 82 | 83 | 84 | } 85 | 86 | remove() { 87 | if(this.arr.length == 0) return; 88 | // remove the highest priority element 89 | 90 | // 1. swap the root with last element 91 | 92 | let temp = this.arr[0]; 93 | this.arr[0] = this.arr[this.arr.length - 1]; 94 | this.arr[this.arr.length - 1] = temp; 95 | 96 | // 2. Remove the last element 97 | this.arr.pop(); 98 | 99 | // 3. downheapify 100 | this.downheapify(0); 101 | 102 | } 103 | 104 | display() { 105 | console.log(this.arr) 106 | } 107 | 108 | get() { 109 | return this.arr[0]; // return the root 110 | } 111 | } 112 | 113 | var mergeKLists = function(lists) { 114 | 115 | let result = new ListNode(123); // 123 is a dummy head 116 | let temp = result; // temp pointer to move on the resultant list // temp = 123-> 117 | 118 | let hp = new Heap((n1, n2) => { 119 | return n1.val > n2.val; 120 | }) 121 | for(let i = 0; i < lists.length; i++) { 122 | if(lists[i]!=null) 123 | hp.insert(lists[i]) 124 | } 125 | 126 | // hp -> [1,1,2] 127 | 128 | while(!hp.isEmpty()) { 129 | let root = hp.get(); // 1->4->% 130 | 131 | // attacyhed my node to the next opf resultant tail node 132 | temp.next = root; // 123->1->4->5 133 | temp = temp.next; // 1->4->5 134 | 135 | 136 | hp.remove(); // remove the node from heap // [1,2] 137 | let nextNode = root.next; // 4->5 138 | root.next = null; // break the conn //. 1 139 | 140 | if(nextNode != null) hp.insert(nextNode); /// [1,2,4] 141 | 142 | 143 | } 144 | 145 | return result.next; 146 | }; -------------------------------------------------------------------------------- /16.Heaps/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/16.Heaps/notes.pdf -------------------------------------------------------------------------------- /16.Heaps/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/16.Heaps/notes2.pdf -------------------------------------------------------------------------------- /17.Graphs/ChecIfPathExistUsingBfs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @param {number[][]} edges 4 | * @param {number} source 5 | * @param {number} destination 6 | * @return {boolean} 7 | */ 8 | 9 | function dfs(src, dest, g, visited) { 10 | if(src == dest) return true; 11 | visited.add(src); // add the source node to visited as we have visited it and now will go neighbours 12 | let ans = false; 13 | for(const neighbour of g[src]) { 14 | if(!visited.has(neighbour)) { 15 | // if we have not already visited the neighbour go 16 | ans = ans || dfs(neighbour, dest, g, visited); 17 | } 18 | } 19 | return ans; 20 | 21 | } 22 | 23 | function bfs(src, dest, g, visited) { 24 | if(src == dest) return true; 25 | const qu = []; 26 | qu.push(src); 27 | visited.add(src); 28 | while(!(qu.length == 0)) { 29 | const el = qu.shift(); 30 | for(const neighbour of g[el]) { 31 | if(neighbour == dest) return true; 32 | if(!visited.has(neighbour)) { 33 | visited.add(neighbour); 34 | qu.push(neighbour); 35 | } 36 | } 37 | } 38 | 39 | return false; 40 | } 41 | 42 | var validPath = function(n, edges, source, destination) { 43 | // created the graph 44 | const g = new Array(n); 45 | 46 | for(let i = 0; i < n; i++) { 47 | g[i] = []; 48 | } 49 | 50 | // populated the graph 51 | for(let i = 0; i < edges.length; i++) { 52 | let u = edges[i][0]; 53 | let v = edges[i][1]; 54 | g[u].push(v); 55 | g[v].push(u); 56 | } 57 | return bfs(source, destination, g, new Set()); 58 | 59 | 60 | }; -------------------------------------------------------------------------------- /17.Graphs/CheckIfPathExist.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @param {number[][]} edges 4 | * @param {number} source 5 | * @param {number} destination 6 | * @return {boolean} 7 | */ 8 | // O(V+E) 9 | function dfs(src, dest, g, visited) { 10 | if(src == dest) return true; 11 | visited.add(src); // add the source node to visited as we have visited it and now will go neighbours 12 | let ans = false; 13 | for(const neighbour of g[src]) { 14 | if(!visited.has(neighbour)) { 15 | // if we have not already visited the neighbour go 16 | ans = ans || dfs(neighbour, dest, g, visited); 17 | } 18 | } 19 | return ans; 20 | } 21 | 22 | var validPath = function(n, edges, source, destination) { 23 | // created the graph 24 | const g = new Array(n); 25 | 26 | for(let i = 0; i < n; i++) { 27 | g[i] = []; 28 | } 29 | 30 | // populated the graph 31 | for(let i = 0; i < edges.length; i++) { 32 | let u = edges[i][0]; 33 | let v = edges[i][1]; 34 | g[u].push(v); 35 | g[v].push(u); 36 | } 37 | return dfs(source, destination, g, new Set()); 38 | 39 | 40 | }; -------------------------------------------------------------------------------- /17.Graphs/RottenOranges.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} grid 3 | * @return {number} 4 | */ 5 | 6 | let neighbours = [[-1, 0], [0, -1], [1, 0], [0, 1]]; 7 | //. i-1, j. i, j-1. i+1, j i, j+1 8 | 9 | function bfs(grid) { 10 | let qu = []; // intialised a queue 11 | let m = grid.length; // rows 12 | let n = grid[0].length; // cols 13 | for(let i = 0; i < m; i++) { 14 | for(let j = 0; j < n; j++) { 15 | if(grid[i][j] === 2 ) // if the current orange is rotten 16 | qu.push([ [i, j], 0 ]) // add coordinate of orange to queue with t = 0, add all sources 17 | } 18 | } 19 | 20 | let result = 0; 21 | 22 | while(!(qu.length == 0)) { 23 | let curr = qu.shift(); 24 | let coords = curr[0]; // coordinates of the current rotten orange 25 | let tm = curr[1]; // time at which current orange was rotten 26 | for(let ni = 0; ni < 4; ni++) { 27 | let nx = coords[0] + neighbours[ni][0]; 28 | let ny = coords[1] + neighbours[ni][1]; 29 | if(nx < 0 || ny < 0 || nx >= m || ny >= n) continue; // outside the grid 30 | if(grid[nx][ny] == 1) { 31 | //console.log(nx, ny, grid[nx][ny]) 32 | qu.push([[nx, ny], tm+1]); 33 | result = Math.max(result, tm+1); 34 | grid[nx][ny] = 2; // mark as rotten 35 | } 36 | } 37 | } 38 | for(let i = 0; i < m; i++) { 39 | for(let j = 0; j < n; j++) { 40 | if(grid[i][j] == 1) return -1; 41 | } 42 | } 43 | return result; 44 | } 45 | 46 | var orangesRotting = function(grid) { 47 | return bfs(grid); 48 | }; -------------------------------------------------------------------------------- /17.Graphs/adjacencyMatrix.js: -------------------------------------------------------------------------------- 1 | class Graph { 2 | constructor(noOfvertices) { 3 | this.v = noOfvertices; 4 | this.adjMat = new Array(this.v); 5 | for(let i = 0; i < this.v; i++) { 6 | this.adjMat[i] = new Array(this.v).fill(0); 7 | } 8 | } 9 | 10 | addEdge(v1, v2, biDir = true) { 11 | this.adjMat[v1][v2] = 1; 12 | if(biDir) { 13 | this.adjMat[v2][v1] = 1; 14 | } 15 | } 16 | 17 | 18 | display() { 19 | console.log(this.adjMat); 20 | } 21 | } 22 | 23 | 24 | const g = new Graph(7); 25 | g.addEdge(0, 1); 26 | g.addEdge(0, 6); 27 | g.addEdge(6, 5); 28 | g.addEdge(1, 5); 29 | g.addEdge(1, 2); 30 | g.addEdge(2, 4); 31 | g.addEdge(2, 3); 32 | g.addEdge(4, 3); 33 | 34 | g.display(); 35 | 36 | -------------------------------------------------------------------------------- /17.Graphs/courseSchedule1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} numCourses 3 | * @param {number[][]} prerequisites 4 | * @return {boolean} 5 | */ 6 | 7 | function topoSort(g, n, indegree) { 8 | 9 | let qu = []; 10 | let vis = new Set(); 11 | for(let i = 0; i < n; i++) { 12 | if(indegree[i] == 0) { 13 | qu.push(i); // add all those nodes as start whose indegree is 0 14 | vis.add(i); 15 | } 16 | } 17 | let count = 0; 18 | while(!(qu.length == 0)) { 19 | let curr = qu.shift(); 20 | count++; 21 | for(const neighbour of g[curr]) { 22 | if(!vis.has(neighbour)) { 23 | indegree[neighbour]--; 24 | if(indegree[neighbour] == 0) { // if all the dependency of neihbour is gone 25 | qu.push(neighbour); 26 | vis.add(neighbour); 27 | } 28 | } 29 | } 30 | } 31 | 32 | return count == n; 33 | 34 | } 35 | 36 | var canFinish = function(numCourses, prerequisites) { 37 | 38 | // create the graph 39 | let g = new Array(numCourses); 40 | for(let i = 0; i < numCourses; i++) g[i] = new Array(); 41 | 42 | let indegree = new Array(numCourses).fill(0); 43 | 44 | for(let i = 0; i < prerequisites.length; i++) { 45 | const curr = prerequisites[i]; 46 | const a = curr[0]; 47 | const b = curr[1]; 48 | g[b].push(a); // a is dependent on b : b ---> a 49 | indegree[a]++; // because now there is an incoming edge edge on a 50 | } 51 | 52 | 53 | return topoSort(g, numCourses, indegree); 54 | 55 | }; -------------------------------------------------------------------------------- /17.Graphs/courseSchedule2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} numCourses 3 | * @param {number[][]} prerequisites 4 | * @return {number[]} 5 | */ 6 | /** 7 | * @param {number} numCourses 8 | * @param {number[][]} prerequisites 9 | * @return {boolean} 10 | */ 11 | 12 | function topoSort(g, n, indegree) { 13 | 14 | let qu = []; 15 | let vis = new Set(); 16 | for(let i = 0; i < n; i++) { 17 | if(indegree[i] == 0) { 18 | qu.push(i); // add all those nodes as start whose indegree is 0 19 | vis.add(i); 20 | } 21 | } 22 | let count = 0; 23 | let result = []; 24 | while(!(qu.length == 0)) { 25 | let curr = qu.shift(); 26 | count++; 27 | result.push(curr); 28 | for(const neighbour of g[curr]) { 29 | if(!vis.has(neighbour)) { 30 | indegree[neighbour]--; 31 | if(indegree[neighbour] == 0) { // if all the dependency of neihbour is gone 32 | qu.push(neighbour); 33 | vis.add(neighbour); 34 | } 35 | } 36 | } 37 | } 38 | 39 | return count == n ? result : []; 40 | 41 | } 42 | 43 | var findOrder = function(numCourses, prerequisites) { 44 | 45 | // create the graph 46 | let g = new Array(numCourses); 47 | for(let i = 0; i < numCourses; i++) g[i] = new Array(); 48 | 49 | let indegree = new Array(numCourses).fill(0); 50 | 51 | for(let i = 0; i < prerequisites.length; i++) { 52 | const curr = prerequisites[i]; 53 | const a = curr[0]; 54 | const b = curr[1]; 55 | g[b].push(a); // a is dependent on b : b ---> a 56 | indegree[a]++; // because now there is an incoming edge edge on a 57 | } 58 | 59 | 60 | return topoSort(g, numCourses, indegree); 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /17.Graphs/dijkstra.js: -------------------------------------------------------------------------------- 1 | class Heap { 2 | constructor(cmp) { 3 | this.arr = []; 4 | this.cmp = cmp; 5 | } 6 | 7 | upheapify(idx) { 8 | // idx represents the index to start upheapify from 9 | while(idx > 0) { 10 | // till the time idx doesnt reach the root 11 | let pi = Math.floor((idx-1)/2); 12 | if(this.cmp(this.arr[pi] , this.arr[idx])) { 13 | // parent is smaller than current element 14 | 15 | // swap the parent and child 16 | let temp = this.arr[pi]; 17 | this.arr[pi] = this.arr[idx]; 18 | this.arr[idx] = temp; 19 | 20 | 21 | idx = pi; 22 | } else { 23 | // everything is good, we have a heap 24 | break; 25 | } 26 | } 27 | } 28 | 29 | insert(data) { 30 | // 1. Insert this data in your array 31 | this.arr.push(data); 32 | 33 | // 2. upheapify 34 | this.upheapify(this.arr.length - 1); 35 | } 36 | 37 | downheapify(idx) { 38 | while(idx < this.arr.length) { 39 | // 1. Calculate the lc and rc index 40 | let lc = 2*idx + 1; // possible lc index 41 | let rc = 2*idx + 2; // possible rc index 42 | let maxEl = idx; // assume root is the max 43 | if(lc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[lc])) { 44 | // left child exist and is greater also 45 | maxEl = lc; 46 | } 47 | 48 | if(rc < this.arr.length && this.cmp(this.arr[maxEl] , this.arr[rc])) { 49 | // right child exist && is greater also 50 | maxEl = rc; 51 | } 52 | 53 | // after the above comparison we klnow the biggest element 54 | if(idx == maxEl) { 55 | // root is still the biggest element, dont go further 56 | break; 57 | } else { 58 | // swap the element of root and maxEl 59 | let temp = this.arr[idx]; 60 | this.arr[idx] = this.arr[maxEl]; 61 | this.arr[maxEl] = temp; 62 | 63 | idx = maxEl; 64 | } 65 | } 66 | 67 | 68 | 69 | } 70 | 71 | remove() { 72 | if(this.arr.length == 0) return; 73 | // remove the highest priority element 74 | 75 | // 1. swap the root with last element 76 | 77 | let temp = this.arr[0]; 78 | this.arr[0] = this.arr[this.arr.length - 1]; 79 | this.arr[this.arr.length - 1] = temp; 80 | 81 | // 2. Remove the last element 82 | this.arr.pop(); 83 | 84 | // 3. downheapify 85 | this.downheapify(0); 86 | 87 | } 88 | 89 | display() { 90 | console.log(this.arr) 91 | } 92 | 93 | isEmpty() { 94 | return this.arr.length == 0; 95 | } 96 | 97 | get() { 98 | return this.arr[0]; // return the root 99 | } 100 | } 101 | 102 | 103 | function dijkstra(n, graph, source) { 104 | let hp = new Heap((a, b) => { // min heap 105 | // [node, distance from source] 106 | return a[1] > b[1] // a< b for max heap, a > b for min heap 107 | }); 108 | 109 | let visited = new Set(); 110 | let via = {}; 111 | let distances = {}; 112 | for(let i = 0; i < n; i++) { 113 | via[i] = undefined; 114 | distances[i] = Infinity; 115 | } 116 | 117 | via[source] = -1; 118 | distances[source] = 0; 119 | 120 | hp.insert([source, 0]); 121 | 122 | while(!hp.isEmpty()) { 123 | let topmost = hp.get(); // get the root node 124 | hp.remove(); // we remove the root node 125 | 126 | const [node, distance] = topmost; // destructuring the node and distance(distance from source to currnode) 127 | 128 | if(visited.has(node)) continue; // if we have already visited this node, then ignore it becuase it is a stale entry 129 | 130 | visited.add(node); // mark the node as visited 131 | 132 | // travel all the neighbours of the current node 133 | for(const neighbour of graph[node]) { 134 | const [neighbourNode, neighbourDistance] = neighbour; // destructuring the neighbour node and distance 135 | if(visited.has(neighbourNode)) continue; // if we have already visited this neighbour, then ignore it 136 | if(via[neighbourNode] === undefined || distances[neighbourNode] > distance + neighbourDistance) { 137 | // previous found distance was greater than the current distance 138 | via[neighbourNode] = node; // update the via array 139 | distances[neighbourNode] = distance + neighbourDistance; // update the distance array 140 | hp.insert([neighbourNode, distance + neighbourDistance]); // insert this neighbour in the heap 141 | } 142 | } 143 | } 144 | 145 | return [distances, via]; 146 | 147 | 148 | } 149 | 150 | let n = 5; 151 | 152 | let graph = [ 153 | [[1, 4], [2, 8]], 154 | [[0, 4], [2, 2], [3, 5]], 155 | [[0, 8], [1, 2], [3, 5]], 156 | [[1, 5], [2, 5], [4, 6]], 157 | [[3, 6]] 158 | ]; 159 | 160 | const response = dijkstra(n, graph, 0); 161 | console.log("Distances are", response[0]); 162 | console.log("Via array is", response[1]); 163 | 164 | /** 165 | * 166 | * [ 167 | * [[1, wt],[2, wt],3] 168 | * [0,2,3] 169 | * [3,4] 170 | * ] 171 | */ -------------------------------------------------------------------------------- /17.Graphs/dsu.js: -------------------------------------------------------------------------------- 1 | function UNION(x, y, parent, size) { 2 | // O(log*n) 3 | let xRoot = FIND(x, parent); 4 | let yRoot = FIND(y, parent); 5 | 6 | if (xRoot === yRoot) return; // x and y are already in the same set 7 | 8 | if (size[xRoot] < size[yRoot]) { 9 | // x is smaller than y 10 | parent[xRoot] = yRoot; 11 | size[yRoot] += size[xRoot]; 12 | } else { 13 | // y is smaller than x 14 | parent[yRoot] = xRoot; 15 | size[xRoot] += size[yRoot]; 16 | } 17 | } 18 | 19 | function FIND(x, parent) { 20 | // O(log*n) 21 | if (parent[x] !== x) { 22 | // if x is not the parent of itself 23 | parent[x] = FIND(parent[x], parent); // Step of path compression 24 | } 25 | return parent[x]; // return the parent of x 26 | } 27 | 28 | // Runner code 29 | let parent = [0, 1, 2, 3, 4, 5]; 30 | let size = [1, 1, 1, 1, 1, 1]; 31 | 32 | UNION(0, 1, parent, size); 33 | UNION(2, 3, parent, size); 34 | UNION(4, 5, parent, size); 35 | 36 | console.log(parent); // Output: [1, 1, 3, 3, 5, 5] 37 | console.log(size); // Output: [1, 2, 1, 2, 1, 2] -------------------------------------------------------------------------------- /17.Graphs/graph.js: -------------------------------------------------------------------------------- 1 | class Graph { 2 | constructor(noOfVertices) { 3 | this.v = noOfVertices; 4 | this.adjList = new Array(this.v); 5 | for(let i = 0; i < this.v; i++) { 6 | this.adjList[i] = []; 7 | } 8 | } 9 | 10 | addEdge(v1, v2, biDir = true) { 11 | this.adjList[v1].push(v2); 12 | if(biDir) { 13 | this.adjList[v2].push(v1) 14 | } 15 | } 16 | 17 | display() { 18 | console.log(this.adjList); 19 | } 20 | } 21 | 22 | const g = new Graph(7); 23 | g.addEdge(0, 1); 24 | g.addEdge(0, 6); 25 | g.addEdge(6, 5); 26 | g.addEdge(1, 5); 27 | g.addEdge(1, 2); 28 | g.addEdge(2, 4); 29 | g.addEdge(2, 3); 30 | g.addEdge(4, 3); 31 | 32 | g.display(); 33 | 34 | -------------------------------------------------------------------------------- /17.Graphs/kruskals.js: -------------------------------------------------------------------------------- 1 | function UNION(x, y, parent, size) { 2 | // O(log*n) 3 | let xRoot = FIND(x, parent); 4 | let yRoot = FIND(y, parent); 5 | 6 | if (xRoot === yRoot) return; // x and y are already in the same set 7 | 8 | if (size[xRoot] < size[yRoot]) { 9 | // x is smaller than y 10 | parent[xRoot] = yRoot; 11 | size[yRoot] += size[xRoot]; 12 | } else { 13 | // y is smaller than x 14 | parent[yRoot] = xRoot; 15 | size[xRoot] += size[yRoot]; 16 | } 17 | } 18 | 19 | function FIND(x, parent) { 20 | // O(log*n) 21 | if (parent[x] !== x) { 22 | // if x is not the parent of itself 23 | parent[x] = FIND(parent[x], parent); // Step of path compression 24 | } 25 | return parent[x]; // return the parent of x 26 | } 27 | 28 | function kruskals(edgeList, noOfVertices) { 29 | // O(ElogE) 30 | edgeList.sort((e1, e2) => e1[2] - e2[2]); // Sort the edges by weight 31 | 32 | let spanningTreeSum = 0; 33 | 34 | let parent = new Array(noOfVertices).fill(0); 35 | parent = parent.map((element, index) => index); // Initialize parent array with each vertex as its own parent 36 | let size = new Array(noOfVertices).fill(1); // Initialize size array with 1 37 | 38 | for (let edge of edgeList) { 39 | let [u, v, weight] = edge; 40 | 41 | if (FIND(u, parent) !== FIND(v, parent)) { 42 | // If u and v are not in the same set 43 | // it means adding this edge will not form a cycle 44 | UNION(u, v, parent, size); 45 | // picking the edge 46 | spanningTreeSum += weight; 47 | } 48 | 49 | } 50 | 51 | return spanningTreeSum; 52 | 53 | } 54 | 55 | // Runner code 56 | let edgeList = [ 57 | [0, 1, 10], 58 | [0, 2, 6], 59 | [0, 3, 5], 60 | [1, 3, 15], 61 | [2, 3, 4] 62 | ]; 63 | let noOfVertices = 4; 64 | console.log(kruskals(edgeList, noOfVertices)); // Output: 19 (10 + 6 + 4 -------------------------------------------------------------------------------- /17.Graphs/maxAreaOfIsland.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} grid 3 | * @return {number} 4 | */ 5 | 6 | let neighbours = [[-1, 0], [0, -1], [1, 0], [0, 1]]; 7 | 8 | function bfs(i, j, grid) { 9 | let qu = []; 10 | qu.push([i, j]); // push the starting point 11 | // mark this src cell visited 12 | grid[i][j] = -1; 13 | let res = 1; // every cc is of size atleast 1 14 | while(!(qu.length == 0)) { 15 | let curr = qu.shift(); // qu.pop //[i, j] 16 | for(let n = 0; n < 4; n++) { 17 | let newNeighbourX = curr[0] + neighbours[n][0]; // n=0 i-1, n=1 i, n=2 i+1, n=3 i 18 | let newNeighbourY = curr[1] + neighbours[n][1]; // n=0 j, n-1 j-1, n=2 j, n=3 j+1 19 | if(newNeighbourX < 0 || newNeighbourY < 0 || newNeighbourX >= grid.length || newNeighbourY >= grid[0].length) { 20 | // we are out side the grid 21 | continue; 22 | } 23 | if(grid[newNeighbourX][newNeighbourY] === 1) { 24 | // its a unvisited piece of land 25 | grid[newNeighbourX][newNeighbourY] = -1; 26 | qu.push([newNeighbourX, newNeighbourY]); 27 | res++; 28 | } 29 | } 30 | } 31 | 32 | return res; 33 | } 34 | 35 | var maxAreaOfIsland = function(grid) { 36 | let cc = 0; 37 | for(let i = 0; i < grid.length; i++) { 38 | for(let j = 0; j < grid[0].length; j++) { 39 | if(grid[i][j] === 1) { 40 | cc = Math.max(cc, bfs(i, j, grid)); 41 | } 42 | } 43 | } 44 | return cc; 45 | }; -------------------------------------------------------------------------------- /17.Graphs/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/17.Graphs/notes1.pdf -------------------------------------------------------------------------------- /17.Graphs/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/17.Graphs/notes2.pdf -------------------------------------------------------------------------------- /17.Graphs/notes3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/17.Graphs/notes3.pdf -------------------------------------------------------------------------------- /17.Graphs/notes4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/17.Graphs/notes4.pdf -------------------------------------------------------------------------------- /17.Graphs/notes5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/17.Graphs/notes5.pdf -------------------------------------------------------------------------------- /17.Graphs/numberOfIslands.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[][]} grid 3 | * @return {number} 4 | */ 5 | 6 | let neighbours = [[-1, 0], [0, -1], [1, 0], [0, 1]]; 7 | 8 | function bfs(i, j, grid) { 9 | let qu = []; 10 | qu.push([i, j]); // push the starting point 11 | // mark this src cell visited 12 | grid[i][j] = "-1"; 13 | while(!(qu.length == 0)) { 14 | let curr = qu.shift(); // qu.pop //[i, j] 15 | for(let n = 0; n < 4; n++) { 16 | let newNeighbourX = curr[0] + neighbours[n][0]; // n=0 i-1, n=1 i, n=2 i+1, n=3 i 17 | let newNeighbourY = curr[1] + neighbours[n][1]; // n=0 j, n-1 j-1, n=2 j, n=3 j+1 18 | if(newNeighbourX < 0 || newNeighbourY < 0 || newNeighbourX >= grid.length || newNeighbourY >= grid[0].length) { 19 | // we are out side the grid 20 | continue; 21 | } 22 | if(grid[newNeighbourX][newNeighbourY] === "1") { 23 | // its a unvisited piece of land 24 | grid[newNeighbourX][newNeighbourY] = "-1"; 25 | qu.push([newNeighbourX, newNeighbourY]); 26 | } 27 | } 28 | } 29 | } 30 | 31 | var numIslands = function(grid) { 32 | let cc = 0; 33 | for(let i = 0; i < grid.length; i++) { 34 | for(let j = 0; j < grid[0].length; j++) { 35 | if(grid[i][j] === "1") { 36 | bfs(i, j, grid); 37 | cc++; 38 | } 39 | } 40 | } 41 | return cc; 42 | }; -------------------------------------------------------------------------------- /17.Graphs/shortCutGraph.js: -------------------------------------------------------------------------------- 1 | let v = 7; 2 | const g = new Array(v); 3 | for(let i = 0 ; i < v; i++) g[i] = []; 4 | function addEdge(v1, v2, biDir = true) { 5 | g[v1].push(v2); 6 | if(biDir) { 7 | g[v2].push(v1) 8 | } 9 | } 10 | addEdge(0, 1); 11 | addEdge(0, 6); 12 | addEdge(6, 5); 13 | addEdge(1, 5); 14 | addEdge(1, 2); 15 | addEdge(2, 4); 16 | addEdge(2, 3); 17 | addEdge(4, 3); 18 | 19 | console.log(g); 20 | 21 | -------------------------------------------------------------------------------- /2.ArraysAndHashing/1.ValidAnagram/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | * https://leetcode.com/problems/valid-anagram/description/ 6 | */ 7 | var isAnagram = function(s, t) { 8 | if(s.length != t.length) return false; 9 | 10 | // prepare freq map of s 11 | const mp = {}; 12 | 13 | for(let i = 0; i < s.length; i++) { 14 | 15 | if(mp[s[i]]) { 16 | // if it is defined, we land here 17 | mp[s[i]] += 1; 18 | } else { 19 | // if it is undefined, we land here 20 | mp[s[i]] = 1; 21 | } 22 | } 23 | 24 | // this loop matches the characters inside the string t, with the map 25 | for(let i = 0; i < t.length; i++) { 26 | if(mp[t[i]] === undefined) { 27 | // there is a character in t, which is not present in s 28 | return false; 29 | } else { 30 | mp[t[i]] -= 1; // if occ found, dec freq 31 | if(mp[t[i]] == 0) { 32 | delete mp[t[i]]; 33 | } 34 | } 35 | } 36 | 37 | return Object.keys(mp).length == 0; 38 | 39 | }; -------------------------------------------------------------------------------- /3.TimeComplexity/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/3.TimeComplexity/notes.pdf -------------------------------------------------------------------------------- /4.Sorting/bubblesort.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/bubblesort.class -------------------------------------------------------------------------------- /4.Sorting/bubblesort.java: -------------------------------------------------------------------------------- 1 | public class bubblesort { 2 | 3 | public static void bubbleSort(int[] arr) { 4 | int n = arr.length; 5 | for(int i = 0; i < n; i++) { 6 | boolean isSwapped = false; 7 | for(int j = 0; j < n - i - 1; j++) { // why j < n - i - 1 -> because in every iteration we push the biggest element at last so no need to compare that 8 | if(arr[j] > arr[j+1]) { 9 | // adjacent element swapping 10 | int temp = arr[j]; 11 | arr[j] = arr[j+1]; 12 | arr[j+1] = temp; 13 | isSwapped = true; 14 | } 15 | } 16 | // if no swapping occured then array is sorted 17 | if(isSwapped == false) return; // return from function as array is sorted 18 | } 19 | } 20 | 21 | public static void main(String[] args) { 22 | int[] arr = {1,2,3,4,5}; 23 | bubbleSort(arr); 24 | for (int i : arr) { 25 | System.out.println(i); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /4.Sorting/insertionsrot.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/insertionsrot.class -------------------------------------------------------------------------------- /4.Sorting/insertionsrot.java: -------------------------------------------------------------------------------- 1 | public class insertionsrot { 2 | public static void insertionsort(int[] arr) { 3 | /** 4 | * Space: O(1) 5 | * Time: O(n^2) 6 | */ 7 | for(int i = 1; i < arr.length; i++) { 8 | int element = arr[i]; 9 | int j; 10 | for(j = i-1; j >= 0; j--) { 11 | if(arr[j] > element) { 12 | arr[j+1] = arr[j]; 13 | } else { 14 | // arr[j] <= element 15 | break; 16 | } 17 | } 18 | arr[j+1] = element; 19 | } 20 | } 21 | public static void main(String[] args) { 22 | int[] arr = {4,5,-1,2,-8,3}; 23 | insertionsort(arr); 24 | for (int i : arr) { 25 | System.out.println(i); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /4.Sorting/merge2sortedarrays.java: -------------------------------------------------------------------------------- 1 | public class merge2sortedarrays { 2 | public void merge(int[] nums1, int m, int[] nums2, int n) { 3 | // actual length of nums1 is m+n, which we will use to store the final result 4 | 5 | int i = 0, j = 0, k = 0; 6 | 7 | int[] result = new int[m + n]; 8 | 9 | while ( i < m && j < n) { // this loop ends when either i == m or j == n 10 | if(nums1[i] <= nums2[j]) { 11 | result[k] = nums1[i]; 12 | k++; 13 | i++; 14 | } else { 15 | result[k] = nums2[j]; 16 | k++; 17 | j++; 18 | } 19 | } 20 | 21 | // if i == m, nums1 is exhausted 22 | // we have elements left in nums2, lets fill that directly 23 | while(j < n) { 24 | result[k] = nums2[j]; 25 | k++; 26 | j++; 27 | } 28 | 29 | // if j == n, nums2 is exhausted 30 | // we have elements left in nums1, lets fill that directly 31 | while(i < m) { 32 | result[k] = nums1[i]; 33 | k++; 34 | i++; 35 | } 36 | 37 | k = 0; 38 | while(k < m + n) { 39 | nums1[k] = result[k]; 40 | k++; 41 | } 42 | 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /4.Sorting/mergesort.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/mergesort.class -------------------------------------------------------------------------------- /4.Sorting/mergesort.java: -------------------------------------------------------------------------------- 1 | public class mergesort { 2 | 3 | public static int[] merge(int[] left, int[] right) { 4 | int i = 0, j = 0, k = 0; 5 | int m = left.length; 6 | int n = right.length; 7 | 8 | int[] result = new int[m + n]; 9 | 10 | while ( i < m && j < n) { // this loop ends when either i == m or j == n 11 | if(left[i] <= right[j]) { 12 | result[k] = left[i]; 13 | k++; 14 | i++; 15 | } else { 16 | result[k] = right[j]; 17 | k++; 18 | j++; 19 | } 20 | } 21 | 22 | // if i == m, nums1 is exhausted 23 | // we have elements left in nums2, lets fill that directly 24 | while(j < n) { 25 | result[k] = right[j]; 26 | k++; 27 | j++; 28 | } 29 | 30 | // if j == n, nums2 is exhausted 31 | // we have elements left in nums1, lets fill that directly 32 | while(i < m) { 33 | result[k] = left[i]; 34 | k++; 35 | i++; 36 | } 37 | 38 | return result; 39 | } 40 | 41 | 42 | public static int[] mergeSortHelper(int[] arr, int start, int end) { 43 | if(start == end) { 44 | int[] result=new int[1]; 45 | result[0] = arr[start]; 46 | return result; 47 | } 48 | int mid = (start + end) / 2; 49 | int[] left = mergeSortHelper(arr, start, mid); 50 | int[] right = mergeSortHelper(arr, mid + 1, end); 51 | return merge(left, right); 52 | } 53 | 54 | public static int[] mergeSort(int[] array) { 55 | return mergeSortHelper(array, 0, array.length - 1); 56 | } 57 | public static void main(String[] args) { 58 | int[] arr = {-1,5,-4,-9,0,1,2,-5,-5,3}; 59 | arr = mergeSort(arr); 60 | for(int i = 0; i < arr.length; i++) { 61 | System.out.println(arr[i]); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /4.Sorting/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/notes.pdf -------------------------------------------------------------------------------- /4.Sorting/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/notes2.pdf -------------------------------------------------------------------------------- /4.Sorting/selectionSort.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/4.Sorting/selectionSort.class -------------------------------------------------------------------------------- /4.Sorting/selectionSort.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class selectionSort { 4 | 5 | 6 | public static void selectionsort(int[] arr) { 7 | for(int i = 0; i < arr.length - 1; i++) { 8 | int min_idx = findMinElement(arr, i); 9 | if(min_idx != i) { 10 | int temp = arr[min_idx]; 11 | arr[min_idx] = arr[i]; 12 | arr[i] = temp; 13 | } 14 | } 15 | } 16 | 17 | public static int findMinElement(int[] arr, int i) { 18 | int min_el_idx = i; 19 | for(int j = i + 1; j < arr.length; j++) { 20 | if(arr[j] < arr[min_el_idx]) { 21 | min_el_idx = j; 22 | } 23 | } 24 | return min_el_idx; 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[] arr = {1,3,2,5,1,2,4}; 29 | selectionsort(arr); 30 | for(int i = 0; i < arr.length; i++) { 31 | System.out.println(arr[i]); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /4.Sorting/selectionsort.js: -------------------------------------------------------------------------------- 1 | function selectionSort(arr) { 2 | let n = arr.length; 3 | /** 4 | * We have the unsorted region initially from index 0 5 | * so i denotes the start of unsorted region 6 | */ 7 | for(let i = 0; i < n - 1; i++) { // i < n-1 means we just want to go till second last element 8 | let min_idx = findMinElement(arr, i); 9 | if(min_idx != i) { 10 | // min element and the first element of unsorted region are diff, then swap 11 | let temp = arr[i]; 12 | arr[i] = arr[min_idx]; 13 | arr[min_idx] = temp; 14 | } 15 | } 16 | } 17 | 18 | 19 | /** 20 | * 21 | * This function finds out the index of the minimum element in the array from index [i, n-1] 22 | */ 23 | function findMinElement(arr, i) { 24 | let min_idx_el = i; // initially the first number is min 25 | for(let j = i+1; j < arr.length; j++) { 26 | if(arr[j] < arr[min_idx_el]) { 27 | // if the curr element is smaller than the assumed min element, we update the assumed min element 28 | min_idx_el = j; 29 | } 30 | } 31 | return min_idx_el; 32 | } 33 | 34 | const arr = [9, 1, 0, 6, -2, 4, 8, 10]; 35 | 36 | selectionSort(arr); 37 | 38 | console.log(arr); -------------------------------------------------------------------------------- /5.Searching/ArrangingCoins.java: -------------------------------------------------------------------------------- 1 | public class ArrangingCoins { 2 | public int arrangeCoins(int n) { 3 | long lo = 1; 4 | long hi = n; 5 | long ans = 1; 6 | while (lo <= hi) { 7 | long mid = lo + (hi - lo) / 2; 8 | long value = (mid * (mid + 1)) / 2; 9 | if (value <= n) { 10 | ans = mid; 11 | lo = mid + 1; 12 | } else { 13 | hi = mid - 1; 14 | } 15 | } 16 | return (int) ans; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /5.Searching/ArrangingCoins.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | var arrangeCoins = function(n) { 6 | let lo = 1; 7 | let hi = n; 8 | let ans = 1; 9 | while(lo <= hi) { 10 | let mid = lo + Math.floor((hi - lo) / 2); 11 | let value = Math.floor(((mid)*(mid+1))/2); 12 | // if(value == n) 13 | if(value <= n) { 14 | ans = mid; 15 | lo = mid+1; 16 | } else { 17 | hi = mid-1; 18 | } 19 | } 20 | return ans; 21 | }; -------------------------------------------------------------------------------- /5.Searching/BinarySearch.java: -------------------------------------------------------------------------------- 1 | public class BinarySearch { 2 | /** 3 | * Performs a binary search to find the element x in the array arr. 4 | * 5 | * @param arr The given input array inside which we need to find an element. 6 | * @param x The element expected to be found. 7 | * @return The index of the element if found, otherwise -1. 8 | */ 9 | public static int binarySearch(int[] arr, int x) { 10 | int n = arr.length; 11 | // declare the search space 12 | int lo = 0, hi = n - 1; 13 | 14 | while (lo <= hi) { 15 | int mid = lo + (hi - lo) / 2; 16 | if (arr[mid] == x) { 17 | // we found the index at which x is present 18 | return mid; 19 | } else if (arr[mid] < x) { 20 | // we need to discard the left half 21 | lo = mid + 1; 22 | } else { 23 | // we need to discard the right half 24 | hi = mid - 1; 25 | } 26 | } 27 | // if the loop ends and we never returned in the loop, means element is not present 28 | return -1; 29 | } 30 | 31 | public static void main(String[] args) { 32 | int[] arr = {-6, 1, 4, 7, 8, 9, 19, 22, 34}; 33 | System.out.println(binarySearch(arr, 21)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /5.Searching/CapacityToShipPackages.java: -------------------------------------------------------------------------------- 1 | public class CapacityToShipPackages { 2 | public int shipWithinDays(int[] weights, int D) { 3 | int totalWeights = 0; 4 | int maxWeight = -1; 5 | 6 | for (int weight : weights) { 7 | totalWeights += weight; 8 | maxWeight = Math.max(maxWeight, weight); 9 | } 10 | 11 | int lo = maxWeight, hi = totalWeights; 12 | int ans = hi; 13 | 14 | while (lo <= hi) { 15 | int mid = lo + (hi - lo) / 2; 16 | if (canShipWithMidWeightWithinDdays(weights, mid, D)) { 17 | ans = mid; 18 | hi = mid - 1; 19 | } else { 20 | lo = mid + 1; 21 | } 22 | } 23 | 24 | return ans; 25 | } 26 | 27 | private boolean canShipWithMidWeightWithinDdays(int[] weights, int mid, int D) { 28 | int daysCount = 0; 29 | int tw = 0; 30 | for (int weight : weights) { 31 | if (tw + weight > mid) { 32 | daysCount++; 33 | tw = 0; 34 | } 35 | tw += weight; 36 | } 37 | daysCount++; 38 | return daysCount <= D; 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /5.Searching/CapacityToShipPackages.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} weights 3 | * @param {number} days 4 | * @return {number} 5 | */ 6 | 7 | function canShipWithMidWeightWithinDdays(weights, mid, d) { 8 | let daysCount = 0; 9 | let tw = 0; 10 | for(let i = 0; i < weights.length; i++) { 11 | if(tw + weights[i] > mid) { 12 | daysCount++; 13 | tw = 0; 14 | } 15 | 16 | tw += weights[i]; 17 | } 18 | daysCount++; 19 | return daysCount <= d; 20 | } 21 | 22 | var shipWithinDays = function(weights, days) { 23 | let totalWeights = 0; 24 | let maxWeight = -1; 25 | 26 | for(let i = 0; i < weights.length ; i++) { 27 | totalWeights += weights[i]; 28 | maxWeight = Math.max(maxWeight, weights[i]); 29 | } 30 | 31 | let lo = maxWeight, hi = totalWeights; 32 | let ans = hi; 33 | 34 | while(lo <= hi) { 35 | let mid = lo + Math.floor((hi - lo) / 2); 36 | if(canShipWithMidWeightWithinDdays(weights, mid, days)) { 37 | ans = mid; 38 | hi = mid - 1; 39 | } else { 40 | lo = mid + 1; 41 | } 42 | } 43 | 44 | return ans; 45 | }; -------------------------------------------------------------------------------- /5.Searching/FindFirstAndLastPositionOfElement.java: -------------------------------------------------------------------------------- 1 | public class FindFirstAndLastPositionOfElement { 2 | public static int LowerBound(int[] arr, int x) { 3 | int n = arr.length; 4 | int lo = 0, hi = n - 1; 5 | int ans = n; 6 | while (lo <= hi) { 7 | int mid = lo + (hi - lo) / 2; 8 | if (arr[mid] < x) { 9 | lo = mid + 1; // discard the left half 10 | } else { 11 | ans = mid; // we got a candidate ans which is >= x and we can find better on left side 12 | hi = mid - 1; 13 | } 14 | } 15 | return ans; 16 | } 17 | public static int UpperBound(int[] arr, int x) { 18 | int n = arr.length; 19 | int lo = 0, hi = n - 1; 20 | int ans = n; 21 | while (lo <= hi) { 22 | int mid = lo + (hi - lo) / 2; 23 | if (arr[mid] <= x) { 24 | lo = mid + 1; // discard the left half 25 | } else { 26 | ans = mid; // we got a candidate ans which is >= x and we can find better on left side 27 | hi = mid - 1; 28 | } 29 | } 30 | return ans; 31 | } 32 | public int[] searchRange(int[] nums, int target) { 33 | int lb = LowerBound(nums, target); 34 | int[] result = new int[2]; 35 | if(lb == nums.length || nums[lb] != target) { 36 | result[0] = -1; 37 | result[1] = -1; 38 | return result; 39 | } 40 | int ub = UpperBound(nums, target); 41 | result[0] = lb; 42 | result[1] = ub-1; 43 | return result; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /5.Searching/FindFirstAndLastPositionOfElement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | function lowerBound(arr, x) { 7 | let n = arr.length; 8 | let lo = 0, hi = n-1; 9 | let ans = arr.length; 10 | while(lo <= hi) { 11 | let mid = lo + Math.floor((hi - lo) / 2); 12 | if(arr[mid] < x) { 13 | lo = mid + 1; // discard the left half 14 | } else { 15 | ans = mid; // we got a candidate ans which is >= x and we can find btr on left side 16 | hi = mid - 1; 17 | } 18 | } 19 | return ans; 20 | } 21 | function upperBound(arr, x) { 22 | let n = arr.length; 23 | let lo = 0, hi = n-1; 24 | let ans = arr.length; 25 | while(lo <= hi) { 26 | let mid = lo + Math.floor((hi - lo) / 2); 27 | if(arr[mid] <= x) { 28 | lo = mid + 1; // discard the left half 29 | } else { // arr[mid] > x 30 | ans = mid; // we got a candidate ans which is >= x and we can find btr on left side 31 | hi = mid - 1; 32 | } 33 | } 34 | return ans; 35 | } 36 | 37 | var searchRange = function(nums, target) { 38 | let lb = lowerBound(nums, target); 39 | if(lb == nums.length || nums[lb] != target) { 40 | return [-1, -1]; 41 | } 42 | let ub = upperBound(nums, target); 43 | return [lb, ub -1]; 44 | }; -------------------------------------------------------------------------------- /5.Searching/GuessNumberHigherOrLower.java: -------------------------------------------------------------------------------- 1 | public class GuessNumberHigherOrLower { 2 | /** The guess API is defined in the parent class GuessGame. 3 | * @param num, your guess 4 | * @return -1 if my number is higher, 1 if my number is lower, otherwise return 0 5 | * int guess(int num); */ 6 | 7 | public int guessNumber(int n) { 8 | int lo = 1; 9 | int hi = n; 10 | while (lo <= hi) { 11 | int mid = lo + (hi - lo) / 2; 12 | int res = guess(mid); 13 | if (res == 0) { 14 | return mid; 15 | } else if (res == -1) { 16 | hi = mid - 1; 17 | } else { 18 | lo = mid + 1; 19 | } 20 | } 21 | return -1; // Should never reach here if input is within constraints 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /5.Searching/GuessNumberHigherOrLower.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Forward declaration of guess API. 3 | * @param {number} num your guess 4 | * @return -1 if num is higher than the picked number 5 | * 1 if num is lower than the picked number 6 | * otherwise return 0 7 | * var guess = function(num) {} 8 | */ 9 | 10 | /** 11 | * @param {number} n 12 | * @return {number} 13 | */ 14 | var guessNumber = function(n) { 15 | let lo = 1; 16 | let hi = n; 17 | while(lo <= hi) { 18 | let mid = lo + Math.floor((hi - lo) / 2); 19 | if(guess(mid ) == 0) return mid; 20 | else if(guess(mid) == -1) hi = mid-1; 21 | else lo = mid+1; 22 | } 23 | }; -------------------------------------------------------------------------------- /5.Searching/MinimizeTheMaximumDifferencePair.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | // https://leetcode.com/problems/minimize-the-maximum-difference-of-pairs/ 3 | public class MinimizeTheMaximumDifferencePair { 4 | 5 | public boolean canFormAtleastPpairsWithAtmostMidDiff(int[] nums, int p, int mid) { 6 | int i = 0, count = 0; 7 | while(i < nums.length - 1) { 8 | if(nums[i+1] - nums[i] <= mid) { // whether ur diff is atmost mid 9 | count++; 10 | i+=2; 11 | } else { 12 | i++; 13 | } 14 | } 15 | return count >= p; // we need atleast p pairs with max diff as mid 16 | } 17 | 18 | public int minimizeMax(int[] nums, int p) { 19 | Arrays.sort(nums); 20 | int n = nums.length; 21 | int lo = 0, hi = nums[n-1] - nums[0]; 22 | int ans = hi; 23 | while(lo <= hi) { 24 | int mid = lo + (hi - lo) / 2; 25 | if(canFormAtleastPpairsWithAtmostMidDiff(nums, p, mid)) { 26 | ans = mid;; 27 | hi = mid-1; 28 | } else { 29 | lo = mid+1; 30 | } 31 | } 32 | return ans; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /5.Searching/Notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/Notes2.pdf -------------------------------------------------------------------------------- /5.Searching/PeakElement.java: -------------------------------------------------------------------------------- 1 | class PeakElement { 2 | public int findPeakElement(int[] nums) { 3 | 4 | if(nums.length == 1) return 0; 5 | 6 | int l = 0; 7 | int r = nums.length - 1; 8 | 9 | while (l <= r) { 10 | int mid = l + (r - l)/ 2; 11 | 12 | if(mid == 0 && nums[mid] > nums[mid+1]) return mid; // leftmost element being peak 13 | 14 | if(mid == nums.length - 1 && nums[mid] > nums[mid-1]) return mid; // rightmost element being peak 15 | 16 | if(nums[mid] > nums[mid+1] && nums[mid] > nums[mid-1]) return mid; // some internal element being peak 17 | 18 | if (mid < nums.length - 1 && nums[mid] < nums[mid + 1]) { 19 | l = mid + 1; 20 | } else { 21 | if (mid == 0 || nums[mid] > nums[mid - 1]) return mid; 22 | r = mid - 1; 23 | } 24 | } 25 | 26 | return -1; 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /5.Searching/PeakElement.js: -------------------------------------------------------------------------------- 1 | function findPeakElement(nums) { 2 | if(nums.length == 1) return 0; 3 | let l = 0; 4 | let r = nums.length - 1; 5 | 6 | while (l <= r) { 7 | let mid = l + Math.floor((r - l) / 2); 8 | 9 | if(mid == 0 && nums[mid] > nums[mid+1]) return mid; // leftmost element being peak 10 | 11 | if(mid == nums.length - 1 && nums[mid] > nums[mid-1]) return mid; // rightmost element being peak 12 | 13 | if(nums[mid] > nums[mid+1] && nums[mid] > nums[mid-1]) return mid; // some internal element being peak 14 | 15 | 16 | 17 | if (mid < nums.length - 1 && nums[mid] < nums[mid + 1]) { 18 | l = mid + 1; 19 | } else { 20 | if (mid === 0 || nums[mid] > nums[mid - 1]) return mid; 21 | r = mid - 1; 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /5.Searching/Search2dMatrix.java: -------------------------------------------------------------------------------- 1 | public class Search2dMatrix { 2 | public boolean searchMatrix(int[][] matrix, int target) { 3 | int m = matrix.length; // no of rows 4 | int n = matrix[0].length; // no of cols 5 | int lo = 0, hi = m * n - 1; 6 | 7 | while(lo <= hi) { 8 | int mid = lo + (hi - lo) / 2; 9 | int row = mid / n; 10 | int col = mid % n; 11 | 12 | if(matrix[row][col] == target) { 13 | return true; 14 | } else if(matrix[row][col] < target) { 15 | lo = mid + 1; 16 | } else { 17 | hi = mid - 1; 18 | } 19 | } 20 | 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /5.Searching/Search2dMatrix.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} matrix 3 | * @param {number} target 4 | * @return {boolean} 5 | */ 6 | var searchMatrix = function(matrix, target) { 7 | let m = matrix.length; // no of rows 8 | let n = matrix[0].length; // no of cols 9 | let lo = 0, hi = m*n - 1; 10 | while(lo <= hi) { 11 | let mid = lo + Math.floor((hi - lo) / 2); 12 | let row = Math.floor(mid / n); 13 | let col = mid % n; 14 | if(matrix[row][col] == target) { 15 | return true; 16 | } else if(matrix[row][col] < target) { 17 | lo = mid + 1; 18 | } else { 19 | hi = mid - 1; 20 | } 21 | } 22 | return false; 23 | }; -------------------------------------------------------------------------------- /5.Searching/SplitArrayLargestSum.java: -------------------------------------------------------------------------------- 1 | public class SplitArrayLargestSum { 2 | private boolean canSplitInToKSubArraysWithmaxMidSum(int[] nums, int mid, int k) { 3 | int subarrayCount = 0; 4 | int ts = 0; 5 | for (int num : nums) { 6 | if (ts + num > mid) { 7 | subarrayCount++; 8 | ts = 0; 9 | } 10 | ts += num; 11 | } 12 | subarrayCount++; 13 | return subarrayCount <= k; 14 | } 15 | 16 | public int splitArray(int[] nums, int k) { 17 | int totalWeights = 0; 18 | int maxWeight = -1; 19 | 20 | for (int num : nums) { 21 | totalWeights += num; 22 | maxWeight = Math.max(maxWeight, num); 23 | } 24 | 25 | int lo = maxWeight, hi = totalWeights; 26 | int ans = hi; 27 | 28 | while (lo <= hi) { 29 | int mid = lo + (hi - lo) / 2; 30 | if (canSplitInToKSubArraysWithmaxMidSum(nums, mid, k)) { 31 | ans = mid; 32 | hi = mid - 1; 33 | } else { 34 | lo = mid + 1; 35 | } 36 | } 37 | 38 | return ans; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /5.Searching/UpperBound.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/UpperBound.class -------------------------------------------------------------------------------- /5.Searching/UpperBound.java: -------------------------------------------------------------------------------- 1 | public class UpperBound { 2 | /** 3 | * Finds the first position where x could be inserted in sorted order without changing the order of the array. 4 | * 5 | * @param arr The array to search. 6 | * @param x The value to search for. 7 | * @return The lowest index of x if found, otherwise the index where x could be inserted. 8 | */ 9 | public static int upperBound(int[] arr, int x) { 10 | int n = arr.length; 11 | int lo = 0, hi = n - 1; 12 | int ans = n; 13 | while (lo <= hi) { 14 | int mid = lo + (hi - lo) / 2; 15 | if (arr[mid] <= x) { 16 | lo = mid + 1; // discard the left half 17 | } else { 18 | ans = mid; // we got a candidate ans which is >= x and we can find better on left side 19 | hi = mid - 1; 20 | } 21 | } 22 | return ans; 23 | } 24 | 25 | public static void main(String[] args) { 26 | int[] arr = {1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 7, 8, 9}; 27 | System.out.println(upperBound(arr, 3)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /5.Searching/binarysearch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @param {The given input array inside which we need to find an element} arr 4 | * @param {x is the element expected to be found} x 5 | */ 6 | function binarySearch(arr, x) { 7 | let n = arr.length; 8 | // declare the search space 9 | let lo = 0, hi = n-1; 10 | 11 | while(lo <= hi) { 12 | let mid = lo + Math.floor((hi - lo) / 2); 13 | if(arr[mid] == x) { 14 | // we found the index at which x is present 15 | return mid; 16 | } else if(arr[mid] < x) { 17 | // we need to discard the left half 18 | lo = mid + 1; 19 | } else { 20 | // we need to discard the right half 21 | hi = mid - 1; 22 | } 23 | } 24 | // if the loop ends and we never returned in the loop, means element is not present 25 | return -1; 26 | } 27 | 28 | let arr = [-6, 1, 4, 7, 8, 9, 19, 22, 34] 29 | console.log(binarySearch(arr, 21)); -------------------------------------------------------------------------------- /5.Searching/kokoeatingbananas.java: -------------------------------------------------------------------------------- 1 | public class kokoeatingbananas { 2 | // Method to check if all bananas can be eaten at a certain speed 3 | public boolean canEatAllBananasInMidSpeed(int[] piles, int h, int mid) { 4 | // O(n) 5 | int totalHoursByKoko = 0; 6 | for (int i = 0; i < piles.length; i++) { 7 | // total time to finish ith pile, using Math.ceil equivalent for integers 8 | totalHoursByKoko += Math.ceil((double)piles[i]/mid); // mid -> 3 piles[i] => 7 -> 9 | } 10 | 11 | return totalHoursByKoko <= h; 12 | } 13 | 14 | // Method to find the minimum eating speed 15 | public int minEatingSpeed(int[] piles, int h) { 16 | int lo = 1; 17 | int hi = 0; 18 | // Finding the maximum value in piles 19 | for (int pile : piles) { 20 | hi = Math.max(hi, pile); 21 | } // O(n) 22 | int ans = hi; 23 | 24 | while (lo <= hi) { 25 | int mid = lo + (hi - lo) / 2; 26 | 27 | if (canEatAllBananasInMidSpeed(piles, h, mid)) { 28 | ans = mid; 29 | hi = mid - 1; // decreasing the speed 30 | } else { 31 | lo = mid + 1; // increasing the speed 32 | } 33 | } 34 | return ans; 35 | } 36 | 37 | } 38 | 39 | 40 | // O(n + nlog(maxofpiles)) -> O(nlog(maxofpiles)) -------------------------------------------------------------------------------- /5.Searching/kokoeatingbananas.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} piles 3 | * @param {number} h 4 | * @return {number} 5 | */ 6 | 7 | function canEatAllBananasInMidSpeed(piles, h, mid) { 8 | let totalHoursByKoko = 0; 9 | for(let i = 0; i < piles.length; i++) { 10 | totalHoursByKoko += Math.ceil(piles[i] / mid); // total time to finish ith pile 11 | } 12 | 13 | return totalHoursByKoko <= h; 14 | } 15 | 16 | var minEatingSpeed = function(piles, h) { 17 | let lo = 1; 18 | let hi = Math.max(...piles); // O(n) 19 | let ans = 1; 20 | 21 | while(lo <= hi) { 22 | let mid = lo + Math.floor((hi - lo) / 2); 23 | 24 | if(canEatAllBananasInMidSpeed(piles, h, mid)) { 25 | ans = mid; 26 | hi = mid - 1; 27 | } else { 28 | lo = mid + 1; 29 | } 30 | 31 | 32 | } 33 | return ans; 34 | }; -------------------------------------------------------------------------------- /5.Searching/lowerBound.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/lowerBound.class -------------------------------------------------------------------------------- /5.Searching/lowerBound.java: -------------------------------------------------------------------------------- 1 | public class lowerBound { 2 | /** 3 | * Finds the first position where x could be inserted in sorted order without changing the order of the array. 4 | * 5 | * @param arr The array to search. 6 | * @param x The value to search for. 7 | * @return The lowest index of x if found, otherwise the index where x could be inserted. 8 | */ 9 | public static int LowerBound(int[] arr, int x) { 10 | int n = arr.length; 11 | int lo = 0, hi = n - 1; 12 | int ans = n; 13 | while (lo <= hi) { 14 | int mid = lo + (hi - lo) / 2; 15 | if (arr[mid] < x) { 16 | lo = mid + 1; // discard the left half 17 | } else { 18 | ans = mid; // we got a candidate ans which is >= x and we can find better on left side 19 | hi = mid - 1; 20 | } 21 | } 22 | return ans; 23 | } 24 | 25 | public static void main(String[] args) { 26 | int[] arr = {1, 1, 2, 2, 2, 3, 4, 4, 4, 5, 7, 8, 9}; 27 | System.out.println(LowerBound(arr, 2)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /5.Searching/lowerBound.js: -------------------------------------------------------------------------------- 1 | function lowerBound(arr, x) { 2 | let n = arr.length; 3 | let lo = 0, hi = n-1; 4 | let ans = arr.length; 5 | while(lo <= hi) { 6 | let mid = lo + Math.floor((hi - lo) / 2); 7 | if(arr[mid] < x) { 8 | lo = mid + 1; // discard the left half 9 | } else { 10 | ans = mid; // we got a candidate ans which is >= x and we can find btr on left side 11 | hi = mid - 1; 12 | } 13 | } 14 | return ans; 15 | } 16 | 17 | 18 | let arr = [1,1,2,2,2,3,4,4,4,5,7,8,9]; 19 | 20 | console.log(lowerBound(arr, 2)); -------------------------------------------------------------------------------- /5.Searching/notes 4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/notes 4.pdf -------------------------------------------------------------------------------- /5.Searching/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/notes1.pdf -------------------------------------------------------------------------------- /5.Searching/notes3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/5.Searching/notes3.pdf -------------------------------------------------------------------------------- /5.Searching/upperbound.js: -------------------------------------------------------------------------------- 1 | function upperBound(arr, x) { 2 | let n = arr.length; 3 | let lo = 0, hi = n-1; 4 | let ans = arr.length; 5 | while(lo <= hi) { 6 | let mid = lo + Math.floor((hi - lo) / 2); 7 | if(arr[mid] <= x) { 8 | lo = mid + 1; // discard the left half 9 | } else { // arr[mid] > x 10 | ans = mid; // we got a candidate ans which is >= x and we can find btr on left side 11 | hi = mid - 1; 12 | } 13 | } 14 | return ans; 15 | } 16 | 17 | 18 | let arr = [1,1,2,2,2,3,4,4,4,5,7,8,9]; 19 | 20 | console.log(upperBound(arr, 3)); -------------------------------------------------------------------------------- /6.DP/ArithmeticSlices.java: -------------------------------------------------------------------------------- 1 | class ArithmeticSlices { 2 | public static int[] arr; 3 | public static int[] dp = new int[5005]; 4 | public static int f(int i) { 5 | if( i == 0 || i == 1) return 0; // base case 6 | if(dp[i] != -1) return dp[i]; 7 | if( arr[i] - arr[i-1] != arr[i-1] - arr[i-2]) { 8 | return dp[i] = 0; 9 | } else { 10 | return dp[i] = 1 + f(i-1); 11 | } 12 | } 13 | 14 | 15 | public static int fbu() { 16 | // TC: O(n) 17 | // SC: O(n) 18 | for(int i = 0; i < arr.length; i++) { 19 | if( i == 0 || i == 1) dp[i] = 0; 20 | else { 21 | if( arr[i] - arr[i-1] != arr[i-1] - arr[i-2]) { 22 | dp[i] = 0; 23 | } else { 24 | dp[i] = 1 + dp[i-1]; 25 | } 26 | } 27 | } 28 | 29 | // sum all of them 30 | int ans = 0; 31 | for(int i = 0; i < arr.length; i++) { 32 | ans += dp[i]; 33 | } 34 | return ans; 35 | } 36 | 37 | public int numberOfArithmeticSlices(int[] nums) { 38 | // int ans = 0; 39 | arr = nums; 40 | // Arrays.fill(dp, -1); 41 | // for(int i = 0; i < nums.length; i++) { 42 | // ans += f(i); 43 | // } 44 | 45 | return fbu(); 46 | } 47 | } -------------------------------------------------------------------------------- /6.DP/ArithmeticSlices.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | 6 | let arr; 7 | let dp; 8 | 9 | function f(i) { 10 | if(i == 0 || i == 1) return 0; 11 | if(dp[i] != -1) return dp[i]; 12 | if(arr[i] - arr[i-1] != arr[i-1] - arr[i-2]) { 13 | return dp[i] = 0; 14 | } else { 15 | return dp[i] = 1 + f(i-1); 16 | } 17 | } 18 | 19 | var numberOfArithmeticSlices = function(nums) { 20 | arr = nums; 21 | dp = Array(5005).fill(-1); 22 | let ans = 0; 23 | for(let i = 0; i < nums.length; i++) { 24 | ans += f(i); 25 | } 26 | return ans; 27 | }; -------------------------------------------------------------------------------- /6.DP/ArithmeticSlices2.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | import java.util.HashMap; 3 | import java.util.List; 4 | 5 | public class ArithmeticSlices2 { 6 | 7 | public static long[] arr; 8 | public static int fbu() { 9 | int n = arr.length; 10 | int ans = 0; 11 | List > dp = new ArrayList >(); 12 | for(int i = 0; i < n; i++) { 13 | dp.add(new HashMap()); 14 | } 15 | 16 | for(int i = 1; i < n; i++) { 17 | for(int j = 0; j < i; j++) { 18 | long diff = arr[j] - arr[i]; 19 | 20 | if(dp.get(j).containsKey(diff)) { 21 | System.out.println(i + " " + j + " " + diff); 22 | ans += dp.get(j).get(diff); 23 | 24 | if(dp.get(i).containsKey(diff)) { 25 | dp.get(i).put(diff , dp.get(i).get(diff) + dp.get(j).get(diff) + 1); 26 | } else { 27 | dp.get(i).put(diff , dp.get(j).get(diff) + 1); 28 | 29 | } 30 | 31 | } else { 32 | if(dp.get(i).containsKey(diff)) { 33 | dp.get(i).put(diff , dp.get(i).get(diff) + 1); 34 | } else { 35 | dp.get(i).put(diff , 1L); 36 | 37 | } 38 | } 39 | } 40 | } 41 | return ans; 42 | } 43 | 44 | public int numberOfArithmeticSlices(int[] nums) { 45 | arr = new long[nums.length]; 46 | for(int i = 0; i < nums.length; i++) { 47 | arr[i] = (long)nums[i]; 48 | } 49 | return fbu(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /6.DP/ArithmeticSlices2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | 6 | let arr; 7 | let dp; 8 | function fbu() { 9 | let n = arr.length 10 | dp = Array(n); 11 | for(let i = 0; i < dp.length; i++) { 12 | dp[i] = {}; 13 | } 14 | let ans = 0; 15 | 16 | for(let i = 1; i < n; i++) { 17 | for(let j = 0; j < i; j++) { 18 | let diff = arr[i] - arr[j]; 19 | if(dp[j][diff]) { 20 | // whether mapp of index i has diff as the key 21 | ans += dp[j][diff]; 22 | if(dp[i][diff]) { 23 | dp[i][diff] += 1 + dp[j][diff]; 24 | } else { 25 | dp[i][diff] = 1 + dp[j][diff]; 26 | } 27 | 28 | } else { 29 | if(dp[i][diff]) { 30 | dp[i][diff] += 1 31 | } else { 32 | dp[i][diff] = 1 33 | } 34 | } 35 | } 36 | } 37 | 38 | // console.log(dp); 39 | 40 | return ans; 41 | } 42 | 43 | 44 | var numberOfArithmeticSlices = function(nums) { 45 | arr = nums; 46 | return fbu(); 47 | }; -------------------------------------------------------------------------------- /6.DP/CoinChange.java: -------------------------------------------------------------------------------- 1 | public class CoinChange { 2 | 3 | public static int[] c; // global coins array 4 | public static int[] dp; 5 | public int f(int amount) { 6 | if(amount < 0) return Integer.MAX_VALUE; // if amt is less than 0 then its not possible 7 | if(amount == 0) return 0; // if amt is 0, give nothing 8 | if(dp[amount] != -1) return dp[amount]; 9 | int ans = Integer.MAX_VALUE; 10 | int n = c.length; 11 | for(int i = 0; i < n; i++) { // i -> [0, n-1] 12 | if(amount >= c[i]) { 13 | ans = Math.min(ans, f(amount-c[i])); 14 | } 15 | } 16 | 17 | // if ans is still Integer.MAX_VALUE, then this amount is not possible 18 | if(ans == Integer.MAX_VALUE) { 19 | return dp[amount] = Integer.MAX_VALUE; 20 | } 21 | return dp[amount] = 1 + ans; 22 | 23 | } 24 | 25 | public static int f_bu(int value) { 26 | dp = new int[10005]; 27 | dp[0] = 0; 28 | for(int amount = 1; amount <= value; amount++) { 29 | int ans = Integer.MAX_VALUE; 30 | int n = c.length; 31 | for(int i = 0; i < n; i++) { // i -> [0, n-1] 32 | if(amount >= c[i]) { 33 | ans = Math.min(ans, dp[amount-c[i]]); 34 | } 35 | } 36 | if(ans == Integer.MAX_VALUE) { 37 | dp[amount] = Integer.MAX_VALUE; 38 | } else { 39 | dp[amount] = 1 + ans; 40 | } 41 | } 42 | 43 | return dp[value]; 44 | } 45 | 46 | 47 | public int coinChange(int[] coins, int amount) { 48 | c = coins; 49 | // dp = new int[10005]; 50 | // Arrays.fill(dp, -1); 51 | int ans = f_bu(amount); 52 | return (ans == Integer.MAX_VALUE) ? -1 : ans; 53 | } 54 | } -------------------------------------------------------------------------------- /6.DP/CoinChange.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} coins 3 | * @param {number} amount 4 | * @return {number} 5 | */ 6 | 7 | let c; // global coins array 8 | let dp; 9 | function f(amount) { 10 | if(amount < 0) return Number.MAX_SAFE_INTEGER; // if amt is less than 0 then its not possible 11 | if(amount == 0) return 0; // if amt is 0, give nothing 12 | if(dp[amount] != -1) return dp[amount]; 13 | let ans = Number.MAX_SAFE_INTEGER; 14 | let n = c.length; 15 | for(let i = 0; i < n; i++) { // i -> [0, n-1] 16 | if(amount >= c[i]) { 17 | ans = Math.min(ans, f(amount-c[i])); 18 | } 19 | } 20 | 21 | // if ans is still Integer.MAX_VALUE, then this amount is not possible 22 | if(ans == Number.MAX_SAFE_INTEGER) { 23 | return dp[amount] = Number.MAX_SAFE_INTEGER; 24 | } 25 | return dp[amount] = 1 + ans; 26 | 27 | } 28 | 29 | var coinChange = function(coins, amount) { 30 | c = coins; 31 | dp = Array(10005).fill(-1); 32 | let ans = f(amount); 33 | return (ans == Number.MAX_SAFE_INTEGER) ? -1 : ans; 34 | }; -------------------------------------------------------------------------------- /6.DP/CombinationSum4.java: -------------------------------------------------------------------------------- 1 | public class CombinationSum4 { 2 | 3 | public static int[] arr; 4 | public static int[] dp = new int[1005]; 5 | 6 | public static int f(int target) { 7 | if(target == 0) return 1; 8 | if(dp[target] != -1) return dp[target]; 9 | int n = arr.length; 10 | 11 | int result = 0; 12 | 13 | for(int k = 0; k < n; k++) { 14 | if(target - arr[k] >= 0) { 15 | result += f(target - arr[k]); 16 | } 17 | } 18 | 19 | return dp[target] = result; 20 | } 21 | 22 | public static int fbu(int givenTarget) { 23 | 24 | for(int target = 0; target <= givenTarget; target++) { 25 | if(target == 0) dp[target] = 1; 26 | else { 27 | int n = arr.length; 28 | int result = 0; 29 | for(int k = 0; k < n; k++) { 30 | if(target - arr[k] >= 0) { 31 | result += dp[target - arr[k]]; 32 | } 33 | } 34 | dp[target] = result; 35 | } 36 | } 37 | return dp[givenTarget]; 38 | 39 | 40 | } 41 | 42 | 43 | public int combinationSum4(int[] nums, int target) { 44 | arr = nums; 45 | // Arrays.fill(dp, -1); 46 | return fbu(target); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /6.DP/Combinationsum4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | let arr; 7 | let dp; 8 | function f(target) { 9 | if(target == 0) return 1; 10 | if(dp[target] != -1) return dp[target]; 11 | let n = arr.length; 12 | 13 | let result = 0; 14 | 15 | for(let k = 0; k < n; k++) { 16 | if(target - arr[k] >= 0) { 17 | result += f(target - arr[k]); 18 | } 19 | } 20 | 21 | return dp[target] = result; 22 | } 23 | 24 | var combinationSum4 = function(nums, target) { 25 | arr = nums; 26 | dp = Array(1005).fill(-1); 27 | return f(target); 28 | }; -------------------------------------------------------------------------------- /6.DP/Fibonacci.java: -------------------------------------------------------------------------------- 1 | class Fibonacci { 2 | public static int[] dp = new int[100005]; 3 | public static int f(int i) { 4 | if(i == 0 || i == 1) return i; // base case 5 | if(dp[i] != -1) return dp[i]; // if value is not -1 we can directly return ans 6 | // if the above if case doesn't execute, it means subproblem has not been solved 7 | return dp[i] = f(i-1) + f(i-2); 8 | } 9 | 10 | 11 | public static int f_bu(int n) { 12 | dp = new int[100005]; 13 | dp[0] = 0; 14 | dp[1] = 1; 15 | 16 | for(int i = 2; i<= n; i++) { 17 | dp[i] = dp[i-1] + dp[i-2]; 18 | } 19 | 20 | return dp[n]; 21 | } 22 | 23 | public int fib(int n) { 24 | // dp = new int[100005]; 25 | // Arrays.fill(dp, -1); 26 | // return f(n); 27 | return f_bu(n); 28 | } 29 | } -------------------------------------------------------------------------------- /6.DP/Fibonacci.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | 6 | let dp; 7 | 8 | function f(n) { 9 | if(n == 0 || n == 1) return n; 10 | if(dp[n] != -1) return dp[n]; 11 | return dp[n] = f(n-1) + f(n-2); 12 | } 13 | 14 | function f_bu(n) { 15 | dp = Array(100005); 16 | dp[0] = 0; 17 | dp[1] = 1; 18 | for(let i = 2; i<= n; i++) { 19 | dp[i] = dp[i-1] + dp[i-2]; 20 | } 21 | return dp[n]; 22 | } 23 | 24 | var fib = function(n) { 25 | // dp = Array(100005).fill(-1); 26 | return f_bu(n); 27 | }; -------------------------------------------------------------------------------- /6.DP/FriendsPairing.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class FriendsPairing { 4 | public static long mod = 1000000007; 5 | public static long[] dp; 6 | public static long f(int i) { 7 | if(i == 0 || i == 1 || i == 2) { 8 | return i; 9 | } 10 | 11 | if(dp[i] != -1) return dp[i]; 12 | 13 | long singleWays = f(i-1)%mod; 14 | long pairWays = ((i-1)%mod * f(i-2)%mod)%mod; 15 | return dp[i] = ((singleWays%mod) + (pairWays%mod))%mod; 16 | } 17 | public static int numberOfWays(int n) { 18 | // Write your code here. 19 | dp = new long[10005]; 20 | Arrays.fill(dp, -1); 21 | return (int)f(n); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /6.DP/MinimumCostForTickets.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | 3 | public class MinimumCostForTickets { 4 | // https://leetcode.com/problems/minimum-cost-for-tickets/ 5 | public static int[] c; 6 | public static int lastDay; 7 | public static HashSet s; 8 | public static int[] dp; 9 | 10 | public static int f(int day) { 11 | if(day > lastDay) return 0; 12 | if(!s.contains(day)) return f(day+1); 13 | if(dp[day] != -1) return dp[day]; 14 | int ans = Math.min(c[0] + f(day+1), Math.min(c[1] + f(day+7), c[2] + f(day+30))); 15 | 16 | return dp[day] = ans; 17 | } 18 | 19 | public static int f_bu() { 20 | dp = new int[400]; 21 | for(int day = 365; day >= 1; day--) { 22 | if(day > lastDay) dp[day] = 0; 23 | else if(!s.contains(day)) dp[day] = dp[day+1]; 24 | else { 25 | int ans = Math.min(c[0] + dp[day+1], Math.min(c[1] + dp[day+7], c[2] + dp[day+30])); 26 | dp[day] = ans; 27 | } 28 | 29 | } 30 | 31 | return dp[1]; 32 | } 33 | 34 | 35 | public int mincostTickets(int[] days, int[] costs) { 36 | s = new HashSet<>(); 37 | for(int day : days) { 38 | s.add(day); 39 | } 40 | c = costs; 41 | lastDay = days[days.length - 1]; 42 | // dp = new int[400]; 43 | // Arrays.fill(dp, -1); 44 | return f_bu(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /6.DP/MinimumCostForTickets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} days 3 | * @param {number[]} costs 4 | * @return {number} 5 | */ 6 | 7 | let c; 8 | let s; 9 | let lastDay; 10 | let dp; 11 | function f(day) { 12 | if(day > lastDay) return 0; 13 | if(!s.has(day)) return f(day+1); 14 | if(dp[day] != -1) return dp[day]; 15 | 16 | let ans = Math.min(c[0] + f(day+1), c[1] + f(day+7), c[2] + f(day+30)); 17 | 18 | return dp[day] = ans; 19 | 20 | } 21 | 22 | 23 | var mincostTickets = function(days, costs) { 24 | s = new Set(days); 25 | c = costs; 26 | lastDay = days[days.length - 1]; 27 | dp = Array(400).fill(-1); 28 | return f(1); 29 | }; -------------------------------------------------------------------------------- /6.DP/Notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/6.DP/Notes2.pdf -------------------------------------------------------------------------------- /6.DP/Notes3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/6.DP/Notes3.pdf -------------------------------------------------------------------------------- /6.DP/Notes4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/6.DP/Notes4.pdf -------------------------------------------------------------------------------- /6.DP/PerfectSquares.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class PerfectSquares { 4 | 5 | public static int[] c; // global coins array 6 | public static int[] dp; 7 | public int f(int amount) { 8 | if(amount < 0) return Integer.MAX_VALUE; // if amt is less than 0 then its not possible 9 | if(amount == 0) return 0; // if amt is 0, give nothing 10 | if(dp[amount] != -1) return dp[amount]; 11 | int ans = Integer.MAX_VALUE; 12 | int n = c.length; 13 | for(int i = 0; i < n; i++) { // i -> [0, n-1] 14 | if(amount >= c[i]) { 15 | ans = Math.min(ans, f(amount-c[i])); 16 | } else { 17 | break; 18 | } 19 | } 20 | 21 | // if ans is still Integer.MAX_VALUE, then this amount is not possible 22 | if(ans == Integer.MAX_VALUE) { 23 | return dp[amount] = Integer.MAX_VALUE; 24 | } 25 | return dp[amount] = 1 + ans; 26 | 27 | } 28 | 29 | public int numSquares(int n) { 30 | c = new int[100]; 31 | int j = 0; 32 | for(int i = 1; i*i <= 10000; i++) { 33 | c[j] = i*i; 34 | j++; 35 | } 36 | dp = new int[10005]; 37 | Arrays.fill(dp, -1); 38 | int ans = f(n); 39 | return ans; 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /6.DP/Triangle.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | import java.util.List; 3 | 4 | class Triangle { 5 | 6 | public static List > mat; 7 | public static int[][]dp = new int[205][205]; 8 | 9 | public static int f(int row, int col) { 10 | 11 | if(row == mat.size() - 1) { 12 | return mat.get(row).get(col); 13 | } 14 | if(dp[row][col] != -1) return dp[row][col]; 15 | 16 | return dp[row][col] = mat.get(row).get(col) + Math.min(f(row+1, col), f(row+1, col+1)); 17 | } 18 | 19 | public int minimumTotal(List> triangle) { 20 | mat = triangle; 21 | for(int i = 0; i < 205; i++) { 22 | Arrays.fill(dp[i], -1); 23 | } 24 | return f(0,0); 25 | } 26 | } -------------------------------------------------------------------------------- /6.DP/Triangle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} triangle 3 | * @return {number} 4 | */ 5 | 6 | 7 | let matrix; 8 | let dp; 9 | function f(row, col) { 10 | // base case 11 | if(row == matrix.length - 1) { 12 | return matrix[row][col]; 13 | } 14 | if(dp[row][col] != -1) return dp[row][col]; 15 | 16 | return dp[row][col] = matrix[row][col] + Math.min(f(row+1, col), f(row+1, col+1)); 17 | } 18 | 19 | 20 | function fbu() { 21 | dp = Array(205); 22 | for(let i = 0; i < 205; i++) { 23 | dp[i] = Array(205); 24 | } 25 | let n = matrix.length; // total row 26 | // base case 27 | for(let i = 0; i < matrix[n-1].length; i++) { 28 | dp[n-1][i] = matrix[n-1][i]; 29 | } 30 | 31 | 32 | for(let row = n-2; row >= 0; row--) { 33 | for(let col = 0; col < matrix[row].length; col++ ) { 34 | dp[row][col] = matrix[row][col] + Math.min(dp[row+1][col], dp[row+1][col+1]); 35 | } 36 | } 37 | 38 | return dp[0][0]; 39 | 40 | } 41 | 42 | 43 | 44 | var minimumTotal = function(triangle) { 45 | matrix = triangle; 46 | // dp = Array(205); 47 | // for(let i = 0; i < 205; i++) { 48 | // dp[i] = Array(205).fill(-1); 49 | // } 50 | return fbu(); 51 | }; -------------------------------------------------------------------------------- /6.DP/buyandsellstock3.java: -------------------------------------------------------------------------------- 1 | public class buyandsellstock3 { 2 | public static int[] p; 3 | public static int[][][] dp = new int[100005][3][2]; 4 | 5 | public static int f(int i, int k, int on) { 6 | // base case 7 | if(i == p.length) { 8 | // all the days are completed 9 | return 0; 10 | } 11 | 12 | if(dp[i][k][on] != -1) return dp[i][k][on]; 13 | 14 | int ans = Integer.MIN_VALUE; 15 | 16 | // ignore 17 | ans = Math.max(ans, f(i+1, k, on)); 18 | 19 | // try to buy 20 | if(k > 0 && on == 0) { 21 | ans = Math.max(ans, -p[i] + f(i+1, k, 1)); 22 | } 23 | 24 | // try to sell 25 | if(on == 1) { 26 | ans = Math.max(ans, p[i] + f(i+1, k-1, 0)); 27 | } 28 | 29 | return dp[i][k][on] = ans; 30 | } 31 | public int maxProfit(int[] prices) { 32 | for(int i = 0; i < 100005; i++) { 33 | for(int j = 0; j < 3; j++) { 34 | for(int k = 0; k < 2; k++) { 35 | dp[i][j][k] = -1; 36 | } 37 | } 38 | } 39 | p = prices; 40 | return f(0, 2, 0); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /6.DP/buyandsellstocks4.java: -------------------------------------------------------------------------------- 1 | public class buyandsellstocks4 { 2 | 3 | public static int[] p; 4 | public static int[][][] dp = new int[1005][105][2]; 5 | 6 | public static int f(int i, int k, int on) { 7 | // base case 8 | if(i == p.length) { 9 | // all the days are completed 10 | return 0; 11 | } 12 | 13 | if(dp[i][k][on] != -1) return dp[i][k][on]; 14 | 15 | int ans = Integer.MIN_VALUE; 16 | 17 | // ignore 18 | ans = Math.max(ans, f(i+1, k, on)); 19 | 20 | // try to buy 21 | if(k > 0 && on == 0) { 22 | ans = Math.max(ans, -p[i] + f(i+1, k, 1)); 23 | } 24 | 25 | // try to sell 26 | if(on == 1) { 27 | ans = Math.max(ans, p[i] + f(i+1, k-1, 0)); 28 | } 29 | 30 | return dp[i][k][on] = ans; 31 | } 32 | 33 | public int maxProfit(int K, int[] prices) { 34 | for(int i = 0; i < 1005; i++) { 35 | for(int j = 0; j < 105; j++) { 36 | for(int k = 0; k < 2; k++) { 37 | dp[i][j][k] = -1; 38 | } 39 | } 40 | } 41 | p = prices; 42 | return f(0, K, 0); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /6.DP/buyandsellstocks4.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} k 3 | * @param {number[]} prices 4 | * @return {number} 5 | */ 6 | let p; 7 | let dp; 8 | function f(i, k, on) { 9 | if(i == p.length) return 0; 10 | 11 | if(dp[i][k][on] != -1) return dp[i][k][on]; 12 | 13 | let ans = Number.MIN_SAFE_INTEGER; 14 | // ignore 15 | ans = Math.max(ans, f(i+1, k, on)); 16 | 17 | // buy 18 | if(k > 0 && on == 0) { 19 | ans = Math.max(ans, -p[i] + f(i+1, k, 1)); 20 | } 21 | 22 | // sell 23 | if(on == 1) { 24 | ans = Math.max(ans, p[i] + f(i+1, k-1, 0)); 25 | } 26 | 27 | return dp[i][k][on] = ans; 28 | } 29 | var maxProfit = function(k, prices) { 30 | p = prices; 31 | dp = new Array(1005); 32 | for(let i = 0; i < 1005; i++) { 33 | dp[i] = new Array(105); 34 | } 35 | for(let i = 0; i < 1005; i++) { 36 | for(let j = 0; j < 105; j++) { 37 | dp[i][j] = new Array(2).fill(-1); 38 | 39 | } 40 | } 41 | let ans = f(0, k, 0); 42 | // console.log(dp); 43 | return ans; 44 | }; -------------------------------------------------------------------------------- /6.DP/lcs.java: -------------------------------------------------------------------------------- 1 | public class lcs { 2 | public static int[][] dp = new int[1005][1005]; 3 | public static int fbu(String s1, String s2) { 4 | // TC:O(nm) 5 | for(int i = 1; i <= s1.length(); i++) { 6 | for(int j = 1; j <= s2.length(); j++) { 7 | if(i == 0 || j == 0) dp[i][j] = 0; 8 | else { 9 | if(s1.charAt(i-1) == s2.charAt(j-1)) { 10 | dp[i][j] = 1 + dp[i-1][j-1]; 11 | } else { 12 | dp[i][j] = Math.max( dp[i-1][j], dp[i][j-1]); 13 | } 14 | } 15 | 16 | } 17 | } 18 | return dp[s1.length()][s2.length()]; 19 | } 20 | public static int f(String s1, String s2, int i, int j) { 21 | if(i == -1 || j == -1) { 22 | // if any one opf the string has been exhausted return 0 23 | return 0; 24 | } 25 | 26 | if(dp[i][j] != -1) return dp[i][j]; 27 | 28 | if(s1.charAt(i) == s2.charAt(j)) { 29 | return dp[i][j] = 1 + f(s1, s2, i-1, j-1); 30 | } else { 31 | return dp[i][j] = Math.max(f(s1, s2, i-1, j), f(s1, s2, i, j-1)); 32 | } 33 | } 34 | 35 | public int longestCommonSubsequence(String text1, String text2) { 36 | // for(int i = 0; i < 1005; i++) { 37 | // for(int j = 0; j < 1005; j++) { 38 | // dp[i][j] = -1; 39 | // } 40 | // } 41 | return fbu(text1, text2); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /6.DP/lcs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} text1 3 | * @param {string} text2 4 | * @return {number} 5 | */ 6 | function f(s1, s2, i, j) { 7 | if(i == -1 || j == -1) return 0; 8 | // TODO: Integrate dp with this recursive solution 9 | if(s1[i] == s2[j]) { 10 | return 1 + f(s1, s2, i-1, j-1); 11 | } else { 12 | return Math.max(f(s1, s2, i-1, j), f(s1, s2, i, j-1)); 13 | } 14 | } 15 | var longestCommonSubsequence = function(text1, text2) { 16 | 17 | return f(text1, text2, text1.length -1, text2.length-1); 18 | }; -------------------------------------------------------------------------------- /6.DP/lis.java: -------------------------------------------------------------------------------- 1 | public class lis { 2 | 3 | public static int[] arr; 4 | public static int[] dp = new int[2505]; 5 | public static int f(int i) { 6 | if(i == 0) return 1; 7 | if(dp[i] != -1) return dp[i]; 8 | int result = 1; 9 | for(int j = 0; j <= i-1; j++) { 10 | if(arr[j] < arr[i]) { 11 | result = Math.max(result, 1 + f(j)); 12 | } 13 | } 14 | 15 | return dp[i] = result; 16 | } 17 | 18 | public static int fbu() { 19 | 20 | for(int i = 0; i < arr.length; i++) { 21 | if(i == 0) dp[i] = 1; 22 | else { 23 | int result = 1; 24 | for(int j = 0; j <= i-1; j++) { 25 | if(arr[j] < arr[i]) { 26 | result = Math.max(result, 1 + dp[j]); 27 | } 28 | } 29 | dp[i] = result; 30 | } 31 | } 32 | 33 | // final ans 34 | int ans = Integer.MIN_VALUE; 35 | for(int i = 0; i < arr.length; i++) { 36 | ans = Math.max(ans, dp[i]); 37 | } 38 | return ans; 39 | 40 | } 41 | 42 | public int lengthOfLIS(int[] nums) { 43 | // int ans = Integer.MIN_VALUE; 44 | // Arrays.fill(dp, -1); 45 | arr = nums; 46 | // for(int i = 0; i < nums.length; i++) { 47 | // ans = Math.max(ans, f(i)); 48 | // } 49 | return fbu(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /6.DP/lps.java: -------------------------------------------------------------------------------- 1 | public class lps { 2 | public static int[][] dp = new int[1005][1005]; 3 | public static int f(String s1, int i, int j) { 4 | if(i == j) return 1; 5 | if(i > j) return 0; 6 | if(dp[i][j] != -1) return dp[i][j]; 7 | if(s1.charAt(i) == s1.charAt(j)) { 8 | return dp[i][j] = 2 + f(s1, i+1, j-1); 9 | } else { 10 | return dp[i][j] = Math.max(f(s1, i+1, j), f(s1, i, j-1)); 11 | } 12 | } 13 | public int longestPalindromeSubseq(String s) { 14 | for(int i = 0; i < 1005; i++) { 15 | for(int j = 0; j < 1005; j++) { 16 | dp[i][j] = -1; 17 | } 18 | } 19 | return f(s, 0, s.length() - 1); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /6.DP/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/6.DP/notes1.pdf -------------------------------------------------------------------------------- /6.DP/notes5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/6.DP/notes5.pdf -------------------------------------------------------------------------------- /7.LinkedList/ListNode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode() {} 7 | * ListNode(int val) { this.val = val; } 8 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 | * } 10 | */ 11 | 12 | public class ListNode { 13 | 14 | int val; 15 | 16 | ListNode next; 17 | 18 | ListNode() {} 19 | 20 | ListNode(int val) { this.val = val; } 21 | 22 | ListNode(int val, ListNode next) { this.val = val; this.next = next; } 23 | } 24 | class removeNthFromLast { 25 | public ListNode removeNthFromEnd(ListNode head, int n) { 26 | ListNode fast = head; 27 | int i = 0; 28 | while(i < n && fast != null) { 29 | i++; 30 | fast = fast.next; 31 | } 32 | if(fast == null) { 33 | // remove head 34 | ListNode newHead = head.next; 35 | head.next = null; 36 | return newHead; 37 | } 38 | ListNode slow = head; 39 | while(fast.next != null) { 40 | // while fast is not at the tail 41 | fast = fast.next; 42 | slow= slow.next; 43 | } 44 | ListNode tbl = slow.next; 45 | slow.next = tbl.next; 46 | tbl.next = null; 47 | return head; 48 | } 49 | } -------------------------------------------------------------------------------- /7.LinkedList/PartitionList.java: -------------------------------------------------------------------------------- 1 | public class PartitionList { 2 | /** 3 | * Definition for singly-linked list. 4 | * public class ListNode { 5 | * int val; 6 | * ListNode next; 7 | * ListNode() {} 8 | * ListNode(int val) { this.val = val; } 9 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 10 | * } 11 | */ 12 | 13 | public ListNode partition(ListNode head, int x) { 14 | ListNode d1 = new ListNode(-1); 15 | ListNode d2 = new ListNode(-1); 16 | 17 | ListNode t1 = d1; 18 | ListNode t2 = d2; 19 | 20 | ListNode curr = head; 21 | while(curr != null) { 22 | ListNode temp = curr; 23 | curr = curr.next; 24 | temp.next = null; 25 | 26 | if(temp.val < x) { 27 | t1.next = temp; 28 | t1 = t1.next;; 29 | 30 | } else { 31 | t2.next = temp; 32 | t2 = t2.next; 33 | } 34 | } 35 | 36 | t1.next = d2.next; 37 | d2.next = null; 38 | ListNode result = d1.next; 39 | d1.next = null; 40 | return result; 41 | 42 | 43 | } 44 | } 45 | class ListNode { 46 | 47 | int val; 48 | 49 | ListNode next; 50 | 51 | ListNode() {} 52 | 53 | ListNode(int val) { this.val = val; } 54 | 55 | ListNode(int val, ListNode next) { this.val = val; this.next = next; } 56 | } -------------------------------------------------------------------------------- /7.LinkedList/ll.js: -------------------------------------------------------------------------------- 1 | var Node = function(data) { 2 | this.data = data; 3 | this.next = null; // until or unless we attach this new node to a list, the next property should be null 4 | } 5 | 6 | 7 | var MyLinkedList = function() { 8 | this.head = null; // because initially everything is empty 9 | }; 10 | 11 | /** 12 | * @param {number} index 13 | * @return {number} 14 | */ 15 | MyLinkedList.prototype.get = function(index) { 16 | let i = 0; 17 | let temp = this.head; 18 | while(i < index && temp != null) { 19 | i++; 20 | temp = temp.next; 21 | } 22 | if(temp == null) return -1; 23 | return temp.data; 24 | }; 25 | 26 | /** 27 | * @param {number} val 28 | * @return {void} 29 | */ 30 | MyLinkedList.prototype.addAtHead = function(val) { 31 | if(this.head == null) { 32 | // means the ll is empty, so this node should become the head 33 | this.head = new Node(val); 34 | } else { 35 | // when ll is not. empty 36 | let n = new Node(val); 37 | n.next = this.head; 38 | this.head = n; 39 | } 40 | }; 41 | 42 | /** 43 | * @param {number} val 44 | * @return {void} 45 | */ 46 | MyLinkedList.prototype.addAtTail = function(val) { 47 | if(this.head == null) { 48 | // ll is empty 49 | this.head = new Node(val); 50 | } else { 51 | let temp = this.head; 52 | while(temp.next != null) { 53 | temp = temp.next; 54 | } 55 | //. when the loop ends, temp points at the tail node 56 | let n = new Node(val); 57 | temp.next = n; 58 | // that's it 59 | } 60 | }; 61 | 62 | /** 63 | * @param {number} index 64 | * @param {number} val 65 | * @return {void} 66 | */ 67 | MyLinkedList.prototype.addAtIndex = function(index, val) { 68 | if(this.head == null && index != 0) return; 69 | if(this.head == null ) { 70 | // console.log("hello") 71 | this.head = new Node(val); 72 | return; 73 | } 74 | if(index == 0) { 75 | this.addAtHead(val); 76 | return; 77 | } 78 | let i = 0; 79 | let prev = null; 80 | let curr = this.head; 81 | while(i < index && curr != null) { 82 | i++; 83 | prev = curr; 84 | curr = curr.next; 85 | } 86 | if(i != index) return; 87 | let n = new Node(val); 88 | prev.next = n; 89 | n.next = curr; 90 | return; 91 | }; 92 | 93 | /** 94 | * @param {number} index 95 | * @return {void} 96 | */ 97 | MyLinkedList.prototype.deleteAtIndex = function(index) { 98 | if(this.head == null) return; 99 | if(index == 0) { 100 | this.deleteAtHead(); 101 | return; 102 | } 103 | let i = 0; 104 | let prev = null; 105 | let nodeToBeDel = this.head; 106 | while(i < index && nodeToBeDel != null) { 107 | prev = nodeToBeDel; 108 | nodeToBeDel = nodeToBeDel.next; 109 | i++; 110 | } 111 | if(i != index) { 112 | // ll was not having the index 113 | return; 114 | } 115 | if(nodeToBeDel == null) return; 116 | let newNext = nodeToBeDel.next; 117 | prev.next = newNext; 118 | nodeToBeDel.next = null; // this now will be later garbage collected 119 | return; 120 | }; 121 | 122 | MyLinkedList.prototype.deleteAtHead = function() { 123 | if(this.head == null) return; 124 | let nextHead = this.head.next; 125 | let nodeToBeDelete = this.head; // curr head 126 | this.head = nextHead; 127 | nodeToBeDelete.next = null; // prev head disconnected 128 | } 129 | 130 | /** 131 | * Your MyLinkedList object will be instantiated and called as such: 132 | * var obj = new MyLinkedList() 133 | * var param_1 = obj.get(index) 134 | * obj.addAtHead(val) 135 | * obj.addAtTail(val) 136 | * obj.addAtIndex(index,val) 137 | * obj.deleteAtIndex(index) 138 | */ -------------------------------------------------------------------------------- /7.LinkedList/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/7.LinkedList/notes1.pdf -------------------------------------------------------------------------------- /7.LinkedList/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/7.LinkedList/notes2.pdf -------------------------------------------------------------------------------- /7.LinkedList/removeDuplicatedFromSortedxList.java: -------------------------------------------------------------------------------- 1 | class ListNode { 2 | 3 | int val; 4 | 5 | ListNode next; 6 | 7 | ListNode() {} 8 | 9 | ListNode(int val) { this.val = val; } 10 | 11 | ListNode(int val, ListNode next) { this.val = val; this.next = next; } 12 | } 13 | public class removeDuplicatedFromSortedxList { 14 | public ListNode deleteDuplicates(ListNode head) { 15 | ListNode curr = head; 16 | while(curr != null && curr.next != null) { 17 | if(curr.val == curr.next.val) { 18 | ListNode toBeRemoved = curr.next; 19 | curr.next = toBeRemoved.next; 20 | toBeRemoved.next = null; 21 | } else { 22 | curr = curr.next; 23 | } 24 | } 25 | return head; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /7.LinkedList/removeDuplicatesFromSortedList.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | var deleteDuplicates = function(head) { 13 | let curr = head; 14 | while(curr != null && curr.next != null) { 15 | if(curr.val == curr.next.val) { 16 | let toBeRemoved = curr.next; 17 | curr.next = toBeRemoved.next; 18 | toBeRemoved.next = null; 19 | } else { 20 | curr = curr.next; 21 | } 22 | } 23 | return head; 24 | }; -------------------------------------------------------------------------------- /7.LinkedList/removeNthNodeFromLast.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} n 11 | * @return {ListNode} 12 | */ 13 | var removeNthFromEnd = function(head, n) { 14 | let fast = head; 15 | let i = 0; 16 | while(i < n && fast != null) { 17 | i++; 18 | fast = fast.next; 19 | } 20 | if(fast == null) { 21 | // remove head 22 | let newHead = head.next; 23 | head.next = null; 24 | return newHead; 25 | } 26 | let slow = head; 27 | while(fast.next != null) { 28 | // till the time fast doesnt reach tail node 29 | slow = slow.next; 30 | fast = fast.next; 31 | } 32 | let toBeDel = slow.next; 33 | slow.next = toBeDel.next; 34 | toBeDel.next = null; 35 | return head; 36 | }; -------------------------------------------------------------------------------- /8.Stacks/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/8.Stacks/.DS_Store -------------------------------------------------------------------------------- /8.Stacks/AsteroidCollision.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class AsteroidCollision { 3 | public int[] asteroidCollision(int[] a) { 4 | Stack st = new Stack<>(); // prepare a stack for storing asteroid 5 | 6 | int i = 0; // this variable points to the current incmoning asteroid 7 | 8 | while(i < a.length) { // till the time we have asteroids left 9 | if(st.isEmpty()) { // if stack is empty 10 | st.push(a[i]); // just push 11 | i++; 12 | } else { 13 | if(st.peek() > 0 && a[i] < 0) { // AST ----> <------incmoing AST 14 | // only coliision condition\ 15 | if(Math.abs(st.peek()) == Math.abs(a[i])) { // if colliding ast have same size 16 | st.pop(); // stored ast is also destroyed 17 | i++; // incoming ast is also destroyed, that y we move to next ast 18 | } else { 19 | // size is not same 20 | if(Math.abs(st.peek()) > Math.abs(a[i])) { // stored >> incming 21 | // incoming ast will be destroyed 22 | i++; // move to next 23 | } else { 24 | while(!st.isEmpty() && st.peek() > 0 && a[i] < 0 && Math.abs(st.peek()) < Math.abs(a[i])) 25 | { 26 | st.pop(); // stored ast is removed 27 | } 28 | } 29 | } 30 | } else { 31 | st.push(a[i]); // no coliision cases 32 | i++; 33 | } 34 | } 35 | } 36 | 37 | int[] result = new int[st.size()]; 38 | for(int idx = result.length - 1; idx >= 0; idx--) { 39 | result[idx] = st.peek(); 40 | st.pop(); 41 | } 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /8.Stacks/BackspaceStrings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | var backspaceCompare = function(s, t) { 7 | const st1 = []; 8 | const st2 = []; 9 | for(let i = 0; i < s.length; i++) { 10 | if(st1.length > 0 && s[i] == '#') { 11 | st1.pop(); 12 | } 13 | else { 14 | if(s[i] != '#') 15 | st1.push(s[i]); 16 | } 17 | } 18 | for(let i = 0; i < t.length; i++) { 19 | if(st2.length > 0 && t[i] == '#') { 20 | st2.pop(); 21 | } 22 | else { 23 | if(t[i] != '#') 24 | st2.push(t[i]); 25 | } 26 | } 27 | console.log(st1, st2); 28 | while(st1.length > 0 && st2.length > 0) { 29 | if(st1[st1.length - 1] != st2[st2.length - 1]) { 30 | return false; 31 | } 32 | st1.pop(); 33 | st2.pop(); 34 | } 35 | 36 | return (st1.length == 0) && (st2.length == 0); 37 | 38 | }; -------------------------------------------------------------------------------- /8.Stacks/BuildArrayWithStackOperations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} target 3 | * @param {number} n 4 | * @return {string[]} 5 | */ 6 | var buildArray = function(target, n) { 7 | const ans = []; // this array can work as stack 8 | let i = 1; 9 | for(const idx in target) { 10 | const element = target[idx]; 11 | while(i < element) { 12 | //console.log(i); 13 | ans.push("Push"); 14 | ans.push("Pop"); 15 | i++; 16 | } 17 | ans.push("Push"); 18 | i++; 19 | } 20 | return ans; 21 | }; 22 | 23 | // [1,2,3] 24 | // [1, 3] 25 | // ["push", "push", "pop", "push"] 26 | 27 | // n = 4 , [1..4] , [1,2,3,4] 28 | 29 | // ["push", "push"] -------------------------------------------------------------------------------- /8.Stacks/MaxFrequencyStack.js: -------------------------------------------------------------------------------- 1 | 2 | var FreqStack = function() { 3 | this.freqMap = {}; 4 | this.maxFreq = 0; 5 | this.elementMap = {}; 6 | }; 7 | 8 | /** 9 | * @param {number} val 10 | * @return {void} 11 | */ 12 | FreqStack.prototype.push = function(val) { 13 | if(!this.freqMap[val]) { 14 | // value is not present in the map 15 | this.freqMap[val] = 1; 16 | } else { 17 | // value is present in the map 18 | this.freqMap[val]+=1; 19 | } 20 | 21 | this.maxFreq = Math.max(this.maxFreq, this.freqMap[val]); 22 | // add the entry in element map 23 | const frequency = this.freqMap[val]; 24 | if(!this.elementMap[frequency]) { 25 | this.elementMap[frequency] = [val]; 26 | } else { 27 | this.elementMap[frequency].push(val); 28 | } 29 | }; 30 | 31 | /** 32 | * @return {number} 33 | */ 34 | FreqStack.prototype.pop = function() { 35 | const arr = this.elementMap[this.maxFreq] 36 | const result = arr[arr.length - 1]; 37 | this.elementMap[this.maxFreq].pop(); 38 | this.freqMap[result]--; 39 | if(this.elementMap[this.maxFreq].length == 0) { 40 | delete this.elementMap[this.maxFreq]; 41 | 42 | this.maxFreq -= 1; 43 | } 44 | return result; 45 | }; 46 | 47 | /** 48 | * Your FreqStack object will be instantiated and called as such: 49 | * var obj = new FreqStack() 50 | * obj.push(val) 51 | * var param_2 = obj.pop() 52 | */ -------------------------------------------------------------------------------- /8.Stacks/RemovingStarsFromString.java: -------------------------------------------------------------------------------- 1 | public class RemovingStarsFromString { 2 | public String removeStars(String s) { 3 | Stack st = new Stack<>(); 4 | int i = 0; 5 | while(i < s.length()) { 6 | if(s.charAt(i) != '*') { 7 | st.push(s.charAt(i)); 8 | } else if(s.charAt(i) == '*' && !st.isEmpty()) { 9 | st.pop(); 10 | } 11 | i++; 12 | } 13 | StringBuilder result = new StringBuilder(""); 14 | while(!st.isEmpty()) { 15 | result.append(st.peek()); 16 | st.pop(); 17 | } 18 | return result.reverse().toString(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /8.Stacks/RemovingStarsFromString.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | class Stack { 6 | // private properties 7 | #arr; 8 | 9 | constructor() { 10 | this.#arr = []; 11 | } 12 | 13 | push(element) { 14 | this.#arr.push(element); 15 | } 16 | 17 | pop() { 18 | this.#arr.pop(); 19 | } 20 | 21 | top() { 22 | return this.#arr[this.#arr.length - 1]; // element present at the last index is the top most element 23 | } 24 | 25 | isEmpty() { 26 | return this.#arr.length == 0; 27 | } 28 | } 29 | var removeStars = function(s) { 30 | let st = new Stack(); 31 | let i = 0; 32 | while(i < s.length) { 33 | if(s[i] != '*') { 34 | st.push(s[i]); 35 | } else if(s[i] == '*' && !st.isEmpty()) { 36 | st.pop(); 37 | } 38 | i++; 39 | } 40 | let result = ""; 41 | while(!st.isEmpty()) { 42 | let ch = st.top(); 43 | st.pop(); 44 | result = ch + result; 45 | } 46 | return result; 47 | 48 | }; -------------------------------------------------------------------------------- /8.Stacks/Stack.js: -------------------------------------------------------------------------------- 1 | class Stack { 2 | // private properties 3 | #arr; 4 | 5 | constructor() { 6 | this.#arr = []; 7 | } 8 | 9 | push(element) { 10 | this.#arr.push(element); 11 | } 12 | 13 | pop() { 14 | this.#arr.pop(); 15 | } 16 | 17 | top() { 18 | return this.#arr[this.#arr.length - 1]; // element present at the last index is the top most element 19 | } 20 | 21 | isEmpty() { 22 | return this.#arr.length == 0; 23 | } 24 | } 25 | 26 | let s = new Stack(); 27 | s.push(10); 28 | s.push(20); 29 | s.push(30); 30 | console.log(s.top()); 31 | s.pop(); // removes 30 32 | console.log(s.top()); 33 | s.pop(); 34 | console.log(s.top()); -------------------------------------------------------------------------------- /8.Stacks/StackusingLL.js: -------------------------------------------------------------------------------- 1 | var Node = function(data) { 2 | this.data = data; 3 | this.next = null; // until or unless we attach this new node to a list, the next property should be null 4 | } 5 | 6 | 7 | var MyLinkedList = function() { 8 | this.head = null; // because initially everything is empty 9 | }; 10 | 11 | /** 12 | * @param {number} val 13 | * @return {void} 14 | */ 15 | MyLinkedList.prototype.addAtHead = function(val) { 16 | if(this.head == null) { 17 | // means the ll is empty, so this node should become the head 18 | this.head = new Node(val); 19 | } else { 20 | // when ll is not. empty 21 | let n = new Node(val); 22 | n.next = this.head; 23 | this.head = n; 24 | } 25 | }; 26 | 27 | 28 | 29 | MyLinkedList.prototype.deleteAtHead = function() { 30 | if(this.head == null) return; 31 | let nextHead = this.head.next; 32 | let nodeToBeDelete = this.head; // curr head 33 | this.head = nextHead; 34 | nodeToBeDelete.next = null; // prev head disconnected 35 | } 36 | 37 | class Stack { 38 | #ll; // private linked list 39 | constructor() { 40 | this.#ll = new MyLinkedList(); 41 | } 42 | 43 | 44 | push(element) { 45 | this.#ll.addAtHead(element); 46 | } 47 | pop() { 48 | this.#ll.deleteAtHead(); 49 | } 50 | top() { 51 | return this.#ll.head.data; 52 | } 53 | isEmpty() { 54 | return this.#ll.head == null; 55 | } 56 | } 57 | 58 | 59 | 60 | let s = new Stack(); 61 | s.push(10); 62 | s.push(20); 63 | s.push(30); 64 | console.log(s.top()); 65 | s.pop(); // removes 30 66 | console.log(s.top()); 67 | s.pop(); 68 | console.log(s.top()); -------------------------------------------------------------------------------- /8.Stacks/notes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/8.Stacks/notes1.pdf -------------------------------------------------------------------------------- /8.Stacks/notes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/8.Stacks/notes2.pdf -------------------------------------------------------------------------------- /9.Queues/notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/singhsanket143/Data-Structures-Algorithms-Problem-Solving/2908a412e560099d8f0504e9c17a01331362ab36/9.Queues/notes.pdf -------------------------------------------------------------------------------- /9.Queues/queueUsingLL.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.next = null; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor() { 10 | this.head = null; // head of the ll 11 | this.tail = null; // tail of the ll 12 | } 13 | 14 | isEmpty() { 15 | return this.head == null; 16 | } 17 | 18 | getHead() { 19 | if(this.head == null) return undefined; 20 | return this.head.data; 21 | } 22 | 23 | getTail() { 24 | if(this.tail == null) return undefined; 25 | return this.tail.data; 26 | } 27 | 28 | removeAtHead() { 29 | if(this.head == null) return; // ll is empty 30 | const newHead = this.head.next; // we will store the new head 31 | this.head.next = null; // disconnect the old head from the ll 32 | this.head = newHead; // allocating the brand new head 33 | 34 | // if head beconmes null after removal of the node means ll is empty now 35 | if(this.head == null) { 36 | this.tail = null; 37 | } 38 | } 39 | 40 | addAtTail(data) { 41 | if(this.head == null) { 42 | // ll is empty 43 | const newNode = new Node(data); 44 | this.head = newNode; 45 | this.tail = newNode; 46 | return; 47 | } else { 48 | const newNode = new Node(data); 49 | this.tail.next = newNode; // we are attaching the new node after the prev tail 50 | this.tail = newNode; // we updated the tail property 51 | } 52 | } 53 | } 54 | 55 | class Queue { 56 | constructor() { 57 | this.ll = new LinkedList(); // we will create a brand new empty list 58 | } 59 | enqueue(data) { 60 | this.ll.addAtTail(data); 61 | } 62 | 63 | dequeue() { 64 | this.ll.removeAtHead(); 65 | } 66 | 67 | isEmpty() { 68 | return this.ll.isEmpty(); 69 | } 70 | 71 | front() { 72 | return this.ll.getHead(); 73 | } 74 | 75 | back() { 76 | return this.ll.getTail(); 77 | } 78 | } 79 | 80 | 81 | // 82 | const qu = new Queue(); 83 | qu.enqueue(10); 84 | qu.enqueue(20); 85 | qu.enqueue(30); 86 | console.log(qu.front(), qu.back()); 87 | qu.dequeue(); 88 | console.log(qu.front(), qu.back()); 89 | qu.dequeue(); 90 | console.log(qu.front(), qu.back()); 91 | qu.dequeue(); 92 | console.log(qu.front(), qu.back()); --------------------------------------------------------------------------------