├── .gitattributes ├── .project ├── .vscode ├── launch.json └── settings.json ├── AlgorithmsChapters ├── BT │ ├── GraphColouring.js │ ├── NQueen.js │ ├── Permutations.js │ ├── SubsetSum.js │ ├── TOH.js │ └── TSP.js ├── CA │ └── IsPrime.js ├── DAC │ ├── ClosestPair.js │ └── NutsAndBolts.js ├── DP │ ├── ALS.js │ ├── CoinChange.js │ ├── DiceThrow.js │ ├── EditDist.js │ ├── Fibo.js │ ├── FloydWarshall.js │ ├── GridMinCost.js │ ├── GridUniqueWays.js │ ├── HouseRobber.js │ ├── JobScheduling.js │ ├── Knapsack.js │ ├── LargestBitonicSubseq.js │ ├── LargestIncreasingSubseq.js │ ├── LargestPalindromicSubsequence.js │ ├── LargestPalindromicSubstr.js │ ├── LongestCommonSubseq.js │ ├── MatrixCM.js │ ├── MinCostBinaryTree.js │ ├── MinStairCost.js │ ├── OptimalBST.js │ ├── StairUniqueWays.js │ ├── StockBuySell.js │ ├── Vacation.js │ └── WildCharMatch.js └── Greedy │ ├── ActivitySelection.js │ ├── ChotaBhim.js │ ├── FractionalKnapsack.js │ ├── HuffmanTree.js │ ├── JobSequencing.js │ ├── JoinRopes.js │ ├── Knapsack.js │ ├── MultipleStageGraph.js │ └── OptimalMergePattern.js ├── Graph ├── Graph.js └── GraphAM.js ├── HashTable ├── CountMap.js ├── HashTableExercise.js ├── HashTableLP.js └── HashTableSC.js ├── Heap └── Heap.js ├── Introduction ├── Analysis.js └── Introduction.js ├── Language and Collections ├── ArrayDemo.js ├── CounterMap.js ├── LoopDemo.js ├── MapDemo.js ├── MinMaxValueTest.js ├── PriorityQueueDemo.js ├── QueueDemo copy.js ├── QueueDemo.js ├── SetDemo.js ├── StackDemo.js └── Tree.js ├── LinkedList ├── CircularLinkedList.js ├── DoublyCircularLinkedList.js ├── DoublyLinkedList.js ├── LinkedList.js └── Poly.js ├── Queue ├── Dequeue.js ├── Queue.js ├── QueueEx.js ├── QueueHalf.js ├── QueueLL.js └── QueueUsingStack.js ├── README.md ├── Searching ├── BitManipulation.js └── Searching.js ├── Sorting ├── BubbleSort.js ├── BucketSort.js ├── CountSort.js ├── InsertionSort.js ├── MergeSort.js ├── QuickSelect.js ├── QuickSort.js ├── RadixSort.js ├── SelectionSort.js ├── ShellSort.js └── SortingEx.js ├── Stack ├── Stack.js ├── StackExercise.js ├── StackLL.js └── TwoStack.js ├── String ├── StringAlgo.js ├── StringMatching.js ├── StringTree.js ├── Stringclass.js ├── TST.js └── Trie.js ├── Tree ├── AVLTree.js ├── BTree.js ├── BinaryIndexTree.js ├── RBTree.js ├── SPLAYTree.js ├── SegmentTree.js ├── Tree.js ├── rangeMaxST.js └── rmqST.js └── how to use this book.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Data-Structures-and-Algorithms-using-JavaScript 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "node", 10 | "request": "launch", 11 | "name": "Launch Program", 12 | "program": "${file}" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "vertice" 4 | ] 5 | } -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/GraphColouring.js: -------------------------------------------------------------------------------- 1 | 2 | function graphColouring2(graph, V, m) { 3 | const colour = new Array(V); 4 | if (graphColouring2Util(graph, V, m, colour, 0)) { 5 | return true; 6 | } 7 | return false; 8 | } 9 | 10 | function graphColouring2Util(graph, V, m, colour, i) { 11 | if (i == V) { 12 | if (isSafe2(graph, colour, V)) { 13 | console.log("Assigned colours are :", colour); 14 | return true; 15 | } 16 | return false; 17 | } 18 | // Assign each colour from 1 to m 19 | for (let j = 1; j <= m; j++) { 20 | colour[i] = j; 21 | if (graphColouring2Util(graph, V, m, colour, i + 1)) { 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | 28 | // Check if the whole graph is coloured properly. 29 | function isSafe2(graph, colour, V) { 30 | for (let i = 0; i < V; i++) { 31 | for (let j = i + 1; j < V; j++) { 32 | if (graph[i][j] && colour[j] == colour[i]) { 33 | return false; 34 | } 35 | } 36 | } 37 | return true; 38 | } 39 | 40 | 41 | function graphColouring(graph, V, m) { 42 | const colour = Array(V).fill(0); 43 | if (graphColouringUtil(graph, V, m, colour, 0)) { 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | function graphColouringUtil(graph, V, m, colour, i) { 50 | if (i == V) { 51 | console.log("Assigned colours are :", colour); 52 | return true; 53 | } 54 | for (let j = 1; j <= m; j++) { 55 | if (isSafe(graph, V, colour, i, j)) { 56 | colour[i] = j; 57 | if (graphColouringUtil(graph, V, m, colour, i + 1)) { 58 | return true; 59 | } 60 | } 61 | } 62 | return false; 63 | } 64 | 65 | // Is it safe to colour vth vertice with c colour. 66 | function isSafe(graph, V, colour, v, c) { 67 | for (let i = 0; i < V; i++) { 68 | if (graph[v][i] == true && c == colour[i]) { 69 | return false; 70 | } 71 | } 72 | return true; 73 | } 74 | 75 | // Testing code. 76 | const graph = [[false, true, false, false, true], 77 | [true, false, true, false, true], 78 | [false, true, false, true, true], 79 | [false, false, true, false, true], 80 | [true, true, true, true, false]]; 81 | const V = 5; // Number of vertices 82 | const m = 4; // Number of colours 83 | if (! graphColouring2(graph, V, m)) { 84 | console.log("Solution does not exist"); 85 | } 86 | if (! graphColouring(graph, V, m)) { 87 | console.log("Solution does not exist"); 88 | } 89 | 90 | /* 91 | Assigned colours are : [ 1, 2, 1, 2, 3 ] 92 | Assigned colours are : [ 1, 2, 1, 2, 3 ] 93 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/NQueen.js: -------------------------------------------------------------------------------- 1 | function feasible(Q, k) { 2 | for (let i = 0; i < k; i++) { 3 | if (Q[k] == Q[i] || Math.abs(Q[i] - Q[k]) == Math.abs(i - k)) { 4 | return false; 5 | } 6 | } 7 | return true; 8 | } 9 | 10 | function nQueens(Q, k, n) { 11 | if (k == n) { 12 | console.log(JSON.stringify(Q)); 13 | return; 14 | } 15 | for (let i = 0; i < n; i++) { 16 | Q[k] = i; 17 | if (feasible(Q, k)) { 18 | nQueens(Q, k + 1, n); 19 | } 20 | } 21 | } 22 | 23 | // Testing code. 24 | const Q = new Array(8); 25 | nQueens(Q, 0, 8); 26 | 27 | /* 28 | [0,4,7,5,2,6,1,3] 29 | [0,5,7,2,6,3,1,4] 30 | ... 31 | [7,2,0,5,1,4,6,3] 32 | [7,3,0,2,5,1,6,4] 33 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/Permutations.js: -------------------------------------------------------------------------------- 1 | function swap(arr, i, j) { 2 | let temp = arr[i]; 3 | arr[i] = arr[j]; 4 | arr[j] = temp; 5 | } 6 | 7 | function permutation(arr, i, length) { 8 | if (length == i) { 9 | console.log(arr); 10 | return; 11 | } 12 | for (let j = i; j < length; j++) { 13 | swap(arr, i, j); 14 | permutation(arr, i + 1, length); 15 | swap(arr, i, j); 16 | } 17 | return; 18 | } 19 | 20 | function isValid(arr, n) { 21 | for (let j = 1; j < n; j++) { 22 | if (Math.abs(arr[j] - arr[j - 1]) < 2) { 23 | return false; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | function permutation2(arr, i, length) { 30 | if (length == i) { 31 | if (isValid(arr, length)) { 32 | console.log(arr); 33 | } 34 | return; 35 | } 36 | for (let j = i; j < length; j++) { 37 | swap(arr, i, j); 38 | permutation2(arr, i + 1, length); 39 | swap(arr, i, j); 40 | } 41 | return; 42 | } 43 | function isValid2(arr, i) { 44 | if (i < 1 || Math.abs(arr[i] - arr[i - 1]) >= 2) { 45 | return true; 46 | } 47 | return false; 48 | } 49 | function permutation3(arr, i, length) { 50 | if (length == i) { 51 | console.log(arr); 52 | return; 53 | } 54 | for (let j = i; j < length; j++) { 55 | swap(arr, i, j); 56 | if (isValid2(arr, i)) { 57 | permutation3(arr, i + 1, length); 58 | } 59 | swap(arr, i, j); 60 | } 61 | return; 62 | } 63 | /* Testing code */ 64 | const arr = [1, 2, 3, 4] 65 | permutation(arr, 0, 4); 66 | permutation2(arr, 0, 4); 67 | permutation3(arr, 0, 4); 68 | 69 | /* 70 | [ 1, 2, 3, 4 ] 71 | [ 1, 2, 4, 3 ] 72 | .... 73 | [ 4, 1, 3, 2 ] 74 | [ 4, 1, 2, 3 ] 75 | 76 | [ 2, 4, 1, 3 ] 77 | [ 3, 1, 4, 2 ] 78 | 79 | [ 2, 4, 1, 3 ] 80 | [ 3, 1, 4, 2 ] 81 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/SubsetSum.js: -------------------------------------------------------------------------------- 1 | 2 | function subsetSum(arr, n, target) { 3 | const flags = Array(n).fill(false); 4 | subsetSumUtil(arr, n, flags, 0, 0, target); 5 | } 6 | 7 | function subsetSumUtil(arr, n, flags, sum, curr, target) { 8 | if (target == sum) { 9 | printSubset(flags, arr, n); // Solution found. 10 | return; 11 | } 12 | if (curr >= n || sum > target) { 13 | // constraint check 14 | // Backtracking. 15 | return; 16 | } 17 | // Current element included. 18 | flags[curr] = true; 19 | subsetSumUtil(arr, n, flags, sum + arr[curr], curr + 1, target); 20 | // Current element excluded. 21 | flags[curr] = false; 22 | subsetSumUtil(arr, n, flags, sum, curr + 1, target); 23 | } 24 | 25 | function printSubset(flags, arr, size) { 26 | const out = []; 27 | for (let i = 0; i < size; i++) 28 | if (flags[i]) 29 | out.push(arr[i]); 30 | console.log(out); 31 | } 32 | 33 | // Testing code. 34 | const arr = [15, 22, 14, 26, 32, 9, 16, 8]; 35 | const target = 53; 36 | subsetSum(arr, arr.length, target); 37 | 38 | /* 39 | [ 15, 22, 16 ] 40 | [ 15, 14, 16, 8 ] 41 | [ 22, 14, 9, 8 ] 42 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/TOH.js: -------------------------------------------------------------------------------- 1 | // Towers Of Hanoi problem. 2 | function tohUtil(num, from, to, temp) { 3 | if (num < 1) 4 | return; 5 | tohUtil(num - 1, from, temp, to); 6 | console.log("Move disk " + num + " from peg " + from + " to peg " + to); 7 | tohUtil(num - 1, temp, to, from); 8 | } 9 | 10 | function toh(num) { 11 | console.log("The sequence of moves involved in the Tower of Hanoi are :"); 12 | tohUtil(num, 'A', 'C', 'B'); 13 | } 14 | 15 | // Testing code. 16 | toh(3); 17 | 18 | /* 19 | The sequence of moves involved in the Tower of Hanoi are : 20 | Move disk 1 from peg A to peg C 21 | Move disk 2 from peg A to peg B 22 | Move disk 1 from peg C to peg B 23 | Move disk 3 from peg A to peg C 24 | Move disk 1 from peg B to peg A 25 | Move disk 2 from peg B to peg C 26 | Move disk 1 from peg A to peg C 27 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/BT/TSP.js: -------------------------------------------------------------------------------- 1 | 2 | // Function to find the minimum weight Hamiltonian Cycle 3 | function tspUtil(graph, n, path, pSize, pCost, visited, ans, ansPath) { 4 | if(pCost >= ans) // Ignore useless paths. 5 | return ans; 6 | 7 | const curr = path[pSize - 1]; 8 | if (pSize == n) { 9 | let first = path[0]; 10 | if(graph[curr][0] > 0 && ans > pCost + graph[curr][first]) { 11 | ans = pCost + graph[curr][first]; 12 | for (let i = 0; i <= n; i++) { 13 | ansPath[i] = path[i%n]; 14 | } 15 | } 16 | return ans; 17 | } 18 | 19 | for (let i = 0; i < n; i++) { 20 | if (visited[i] == false && graph[curr][i] > 0) { 21 | visited[i] = true; 22 | path[pSize] = i; 23 | ans = tspUtil(graph, n, path, pSize + 1, pCost + graph[curr][i], visited, ans, ansPath); 24 | visited[i] = false; 25 | } 26 | } 27 | return ans; 28 | } 29 | 30 | function tsp(graph, n) { 31 | const visited = Array(n).fill(false); 32 | const path = Array(n).fill(0); 33 | let ansPath = Array(n).fill(0); 34 | 35 | const source = 0; 36 | visited[source] = true; 37 | path[0] = source; 38 | 39 | let ans = Number.MAX_VALUE; 40 | ans = tspUtil(graph, n, path, 1, 0, visited, ans, ansPath); 41 | 42 | console.log("Shortest Path weight :", ans); 43 | console.log("Shortest Path :", ansPath); 44 | return ans; 45 | } 46 | 47 | // Testing code. 48 | const n = 4; 49 | const graph = [[0, 10, 15, 20], 50 | [10, 0, 35, 25], 51 | [15, 35, 0, 30], 52 | [20, 25, 30, 0]]; 53 | tsp(graph, n); 54 | 55 | /* 56 | Shortest Path weight : 80 57 | Shortest Path : [ 0, 1, 3, 2, 0 ] 58 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/CA/IsPrime.js: -------------------------------------------------------------------------------- 1 | function isPrime(n) { 2 | let answer = (n > 1) ? true : false; 3 | for (let i = 2; i * i <= n; ++i) { 4 | if (n % i == 0) { 5 | answer = false; 6 | break; 7 | } 8 | } 9 | return answer; 10 | } 11 | 12 | // Testing code. 13 | console.log(isPrime(7)); 14 | console.log(isPrime(8)); 15 | 16 | /* 17 | true 18 | false 19 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DAC/ClosestPair.js: -------------------------------------------------------------------------------- 1 | function closestPairBF(arr) { 2 | const n = arr.length; 3 | let dmin = 9999999; 4 | let d = 0.0; 5 | for (let i = 0; i < n - 1; i++) { 6 | for (let j = i + 1; j < n; j++) { 7 | d = Math.sqrt((arr[i][0] - arr[j][0]) * (arr[i][0] - arr[j][0]) + (arr[i][1] - arr[j][1]) * (arr[i][1] - arr[j][1])); 8 | if (d < dmin) { 9 | dmin = d; 10 | } 11 | } 12 | } 13 | return dmin; 14 | } 15 | 16 | class Point { 17 | constructor(a, b) { 18 | this.x = a; 19 | this.y = b; 20 | } 21 | } 22 | 23 | function closestPairDC(arr) { 24 | const n = arr.length; 25 | const p = Array(n).fill(null); 26 | for (let i = 0; i < n; i++) { 27 | p[i] = new Point(arr[i][0], arr[i][1]); 28 | } 29 | // Sort according to x axis. 30 | p.sort(function xComp(s1, s2){ return (s1.x - s2.x);}); 31 | let q = [...p]; 32 | // Sort according to y axis. 33 | q.sort(function yComp(s1, s2){ return (s1.y - s2.y);}); 34 | return closestPairUtil(p, 0, n - 1, q, n); 35 | } 36 | 37 | function closestPairUtil(p, start, stop, q, n) { 38 | if (stop - start < 1) { 39 | return 999999; 40 | } 41 | if (stop - start == 1) { 42 | return distance(p[start], p[stop]); 43 | } 44 | // Find the middle point 45 | let mid = parseInt((start + stop) / 2); 46 | let dl = closestPairUtil(p, start, mid, q, n); 47 | let dr = closestPairUtil(p, mid + 1, stop, q, n); 48 | let d = Math.min(dl, dr); 49 | // Build an array strip[] that contains points whose x axis coordinate 50 | // in the range p[mid]-d and p[mid]+d 51 | // Points are already sorted according to y axis. 52 | let strip = Array(n).fill(null); 53 | let j = 0; 54 | for (let i = 0; i < n; i++) { 55 | if (Math.abs(q[i].x - p[mid].x) < d) { 56 | strip[j] = q[i]; 57 | j++; 58 | } 59 | } 60 | // Find the closest points in strip and compare with d. 61 | return Math.min(d, stripMin(strip, j, d)); 62 | } 63 | 64 | function distance(a, b) { 65 | return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 66 | } 67 | 68 | function stripMin(q, n, d) { 69 | let min = d; 70 | // Find the distance between all the points in the strip. 71 | // Array q is sorted according to the y axis coordinate. 72 | // The inner loop will run at most 6 times for each point. 73 | for (let i = 0; i < n; ++i) { 74 | for (let j = i + 1; j < n && (q[j].y - q[i].y) < min; ++j) { 75 | d = distance(q[i], q[j]); 76 | if (d < min) { 77 | min = d; 78 | } 79 | } 80 | } 81 | return min; 82 | } 83 | 84 | // Testing code. 85 | const arr = [[648, 896], [269, 879], [250, 922], [453, 347], [213, 17]]; 86 | console.log("Smallest distance is:" + closestPairBF(arr)); 87 | console.log("Smallest distance is:" + closestPairDC(arr)); 88 | 89 | /* 90 | Smallest distance is:47.01063709417264 91 | Smallest distance is:47.01063709417264 92 | */ 93 | 94 | function power(x, n) { 95 | let value; 96 | if (n == 0) { 97 | return (1); 98 | } else if (n % 2 == 0) { 99 | value = power(x, Math.floor(n / 2)); 100 | return (value * value); 101 | } else { 102 | value = power(x, Math.floor(n / 2)); 103 | return (x * value * value); 104 | } 105 | } 106 | 107 | // Testing code. 108 | console.log(power(5, 2)); 109 | -------------------------------------------------------------------------------- /AlgorithmsChapters/DAC/NutsAndBolts.js: -------------------------------------------------------------------------------- 1 | function makePairs(nuts, bolts) { 2 | makePairsUtil(nuts, bolts, 0, nuts.length - 1); 3 | console.log("Matched nuts and bolts are : ", nuts, bolts); 4 | } 5 | 6 | // Quick sort kind of approach. 7 | function makePairsUtil(nuts, bolts, low, high) { 8 | if (low < high) { 9 | // Choose first element of bolts array as pivot to partition nuts. 10 | let pivot = partition(nuts, low, high, bolts[low]); 11 | 12 | // Using nuts[pivot] as pivot to partition bolts. 13 | partition(bolts, low, high, nuts[pivot]); 14 | 15 | // Recursively lower and upper half of nuts and bolts are matched. 16 | makePairsUtil(nuts, bolts, low, pivot - 1); 17 | makePairsUtil(nuts, bolts, pivot + 1, high); 18 | } 19 | } 20 | function swap(arr, first, second) { 21 | let temp = arr[first]; 22 | arr[first] = arr[second]; 23 | arr[second] = temp; 24 | } 25 | 26 | // Partition method similar to quick sort algorithm. 27 | function partition(arr, low, high, pivot) { 28 | let i = low; 29 | for (let j = low; j < high; j++) { 30 | if (arr[j] < pivot) { 31 | swap(arr, i, j); 32 | i++; 33 | } else if (arr[j] == pivot) { 34 | swap(arr, high, j); 35 | j--; 36 | } 37 | } 38 | swap(arr, i, high); 39 | return i; 40 | } 41 | 42 | // Testing code. 43 | const nuts = [1, 2, 6, 5, 4, 3]; 44 | const bolts = [6, 4, 5, 1, 3, 2]; 45 | makePairs(nuts, bolts); 46 | 47 | /* 48 | Matched nuts and bolts are : [ 1, 2, 3, 4, 5, 6 ] [ 1, 2, 3, 4, 5, 6 ] 49 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/ALS.js: -------------------------------------------------------------------------------- 1 | function fastestWayBU2(a, t, e, x, n) { 2 | const f1 = Array(n).fill(0); 3 | const f2 = Array(n).fill(0); 4 | 5 | // Time taken to leave first station. 6 | f1[0] = e[0] + a[0][0]; 7 | f2[0] = e[1] + a[1][0]; 8 | 9 | // Fill the tables f1[] and f2[] using 10 | // bottom up approach. 11 | for (let i = 1; i < n; ++i) { 12 | f1[i] = Math.min(f1[i-1] + a[0][i], f2[i-1] + t[1][i-1] + a[0][i]); 13 | f2[i] = Math.min(f2[i-1] + a[1][i], f1[i-1] + t[0][i-1] + a[1][i]); 14 | } 15 | // Consider exit times and return minimum. 16 | return Math.min(f1[n-1] + x[0], f2[n-1] + x[1]); 17 | } 18 | 19 | function fastestWayBU(a, t, e, x, n) { 20 | const f = Array(2).fill(0).map(() => new Array(n).fill(0)); 21 | 22 | // Time taken to leave first station. 23 | f[0][0] = e[0] + a[0][0]; 24 | f[1][0] = e[1] + a[1][0]; 25 | 26 | // Fill the tables f1[] and f2[] using 27 | // bottom up approach. 28 | for (let i = 1; i < n; ++i) { 29 | f[0][i] = Math.min(f[0][i-1] + a[0][i], f[1][i-1] + t[1][i-1] + a[0][i]); 30 | f[1][i] = Math.min(f[1][i-1] + a[1][i], f[0][i-1] + t[0][i-1] + a[1][i]); 31 | } 32 | // Consider exit times and return minimum. 33 | return Math.min(f[0][n-1] + x[0], f[1][n-1] + x[1]); 34 | } 35 | 36 | function fastestWayTD(a, t, e, x, n) { 37 | const f = Array(2).fill(0).map(() => new Array(n).fill(0)); 38 | 39 | // Time taken to leave first station. 40 | f[0][0] = e[0] + a[0][0]; 41 | f[1][0] = e[1] + a[1][0]; 42 | fastestWayTDUtil(f, a, t, n-1); 43 | return Math.min(f[0][n-1] + x[0], f[1][n-1] + x[1]); 44 | } 45 | 46 | function fastestWayTDUtil(f, a, t, i) { 47 | if (i == 0) 48 | return; 49 | 50 | fastestWayTDUtil(f, a, t, i-1); 51 | // Fill the tables f1[] and f2[] using top-down approach. 52 | f[0][i] = Math.min(f[0][i-1] + a[0][i], f[1][i-1] + t[1][i-1] + a[0][i]); 53 | f[1][i] = Math.min(f[1][i-1] + a[1][i], f[0][i-1] + t[0][i-1] + a[1][i]); 54 | } 55 | 56 | /* Testing Code */ 57 | const a = [[7, 9, 3, 4, 8, 4], [8, 5, 6, 4, 5, 7]]; 58 | const t = [[2, 3, 1, 3, 4], [2, 1, 2, 2, 1]]; 59 | const e = [2, 4]; 60 | const x = [3, 2]; 61 | const n = 6; 62 | console.log("Fastest way :", fastestWayBU2(a, t, e, x, n)); 63 | console.log("Fastest way :", fastestWayBU(a, t, e, x, n)); 64 | console.log("Fastest way :", fastestWayTD(a, t, e, x, n)); 65 | 66 | /* 67 | Fastest way : 38 68 | Fastest way : 38 69 | Fastest way : 38 70 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/CoinChange.js: -------------------------------------------------------------------------------- 1 | function minCoins(coins, n, val) { // Greedy may be wrong. 2 | if (val <= 0) 3 | return 0; 4 | 5 | let count = 0; 6 | coins.sort(function(a, b){return a - b;}); 7 | for (let i = n-1; i >= 0 && val > 0;) { 8 | if (coins[i] <= val) { 9 | count++; 10 | val -= coins[i]; 11 | } else { 12 | i--; 13 | } 14 | } 15 | return (val == 0) ? count : -1; 16 | } 17 | 18 | function minCoins2(coins, n, val) { // Brute force. 19 | if (val == 0) 20 | return 0; 21 | 22 | let count = Number.MAX_VALUE; 23 | for (let i = 0; i < n; i++) { 24 | if (coins[i] <= val) { 25 | let subCount = minCoins2(coins, n, val - coins[i]); 26 | if (subCount >= 0) 27 | count = Math.min(count, subCount + 1); 28 | } 29 | } 30 | return (count != Number.MAX_VALUE) ? count : -1; 31 | } 32 | 33 | function minCoinsTD(coins, n, val) { // DP top down approach. 34 | const count = new Array(val + 1); 35 | count.fill(Number.MAX_VALUE); 36 | return minCoinsTDUtil(count, coins, n, val); 37 | } 38 | 39 | function minCoinsTDUtil(count, coins, n, val) { 40 | // Base Case 41 | if (val == 0) 42 | return 0; 43 | 44 | if (count[val] != Number.MAX_VALUE) 45 | return count[val]; 46 | 47 | // Recursion 48 | for (let i = 0; i < n; i++) { 49 | if (coins[i] <= val) { 50 | // check validity of a sub-problem 51 | let subCount = minCoinsTDUtil(count, coins, n, val - coins[i]); 52 | if (subCount != Number.MAX_VALUE) 53 | count[val] = Math.min(count[val], subCount + 1); 54 | } 55 | } 56 | return count[val]; 57 | } 58 | 59 | function minCoinsBU(coins, n, val) { // count bottom up approach. 60 | const count = new Array(val + 1); 61 | count.fill(Number.MAX_VALUE); 62 | count[0] = 0; // Base value. 63 | for (let i = 1; i <= val; i++) { 64 | for (let j = 0; j < n; j++) { 65 | if (coins[j] <= i && count[i - coins[j]] !== Number.MAX_VALUE && count[i] > count[i - coins[j]] + 1) 66 | { 67 | count[i] = count[i - coins[j]] + 1; 68 | } 69 | } 70 | } 71 | 72 | if (count[val] == Number.MAX_VALUE) 73 | return -1; 74 | 75 | return count[val]; 76 | } 77 | 78 | function minCoinsBU2(coins, n, val) { // DP bottom up approach. 79 | const count = new Array(val + 1); 80 | count.fill(Number.MAX_VALUE); 81 | const cvalue = new Array(val + 1); 82 | cvalue.fill(Number.MAX_VALUE); 83 | 84 | count[0] = 0; // Base value. 85 | for (let i = 1; i <= val; i++) { 86 | for (let j = 0; j < n; j++) { 87 | if (coins[j] <= i && count[i - coins[j]] !== Number.MAX_VALUE && count[i] > count[i - coins[j]] + 1) 88 | { 89 | count[i] = count[i - coins[j]] + 1; 90 | cvalue[i] = coins[j]; 91 | } 92 | } 93 | } 94 | 95 | if (count[val] == Number.MAX_VALUE) 96 | return -1; 97 | 98 | printCoins(cvalue, val); 99 | return count[val]; 100 | } 101 | 102 | function printCoinsUtil(cvalue, val) { 103 | if (val > 0) { 104 | const ret = printCoinsUtil(cvalue, val - cvalue[val]); 105 | return ret + cvalue[val] + " "; 106 | } 107 | return ""; 108 | } 109 | 110 | function printCoins(cvalue, val) { 111 | var ret = printCoinsUtil(cvalue, val); 112 | console.log("Coins are : " + ret); 113 | } 114 | 115 | /* Testing Code */ 116 | const coins = [5, 6]; 117 | const value = 16; 118 | const n = coins.length; 119 | console.log("Count is : " + minCoins(coins, n, value)); 120 | console.log("Count is : " + minCoins2(coins, n, value)); 121 | console.log("Count is : " + minCoinsBU(coins, n, value)); 122 | console.log("Count is : " + minCoinsBU2(coins, n, value)); 123 | console.log("Count is : " + minCoinsTD(coins, n, value)); 124 | 125 | /* 126 | Count is : -1 127 | Count is : 3 128 | Count is : 3 129 | Coins are : 6 5 5 130 | Count is : 3 131 | Count is : 3 132 | */ 133 | 134 | -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/DiceThrow.js: -------------------------------------------------------------------------------- 1 | 2 | function findWays(n, m, V) { 3 | const dp = new Array(n + 1); 4 | for (let i = 0; i < (n + 1); i++) 5 | dp[i] = new Array(V + 1).fill(0); 6 | 7 | // Table entries for only one dice. 8 | for (let j = 1; j <= m && j <= V; j++) 9 | dp[1][j] = 1; 10 | 11 | // i is number of dice, j is Value, k value of dice. 12 | for (let i = 2; i <= n; i++) { 13 | for (let j = 1; j <= V; j++) { 14 | for (let k = 1; k <= j && k <= m; k++) 15 | dp[i][j] += dp[i-1][j-k]; 16 | } 17 | } 18 | return dp[n][V]; 19 | } 20 | 21 | /* Testing Code */ 22 | console.log(findWays(3, 6, 6)); 23 | 24 | /* 25 | 10 26 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/EditDist.js: -------------------------------------------------------------------------------- 1 | 2 | function min(x, y, z) { 3 | x = Math.min(x, y); 4 | return Math.min(x, z); 5 | } 6 | 7 | function editDist(str1, str2) { 8 | const m = str1.length; 9 | const n = str2.length; 10 | return editDistUtil(str1, str2, m, n); 11 | } 12 | 13 | function editDistUtil(str1, str2, m, n) { 14 | // If any one string is empty, then empty the other string. 15 | if (m == 0 || n == 0) 16 | return m + n; 17 | 18 | // If last characters of both strings are same, ignore last characters. 19 | if (str1[m-1] == str2[n-1]) 20 | return editDistUtil(str1, str2, m-1, n-1); 21 | 22 | // If last characters are not same, consider all three operations: 23 | // 1) Insert last char of second into first. 24 | // 2) Remove last char of first. 25 | // 3) Replace last char of first with second. 26 | return 1 + min(editDistUtil(str1, str2, m, n-1), 27 | editDistUtil(str1, str2, m-1, n), 28 | editDistUtil(str1, str2, m-1, n-1)); 29 | } 30 | 31 | function editDistDP(str1, str2) { 32 | const m = str1.length; 33 | const n = str2.length; 34 | const dp = Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0)); 35 | 36 | // Fill dp[][] in bottom up manner. 37 | for (let i = 0; i <= m; i++) { 38 | for (let j = 0; j <= n; j++) { 39 | // If any one string is empty, then empty the other string. 40 | if (i == 0 || j == 0) 41 | dp[i][j] = (i + j); 42 | else if (str1[i-1] == str2[j-1]) 43 | dp[i][j] = dp[i-1][j-1]; 44 | // If last characters are not same, consider all three operations: 45 | // (1) Insert last char of second into first. 46 | // (2) Remove last char of first. 47 | // (3) Replace last char of first with second. 48 | else 49 | dp[i][j] = 1 + min(dp[i][j - 1], // Insert 50 | dp[i - 1][j], // Remove 51 | dp[i - 1][j - 1]); // Replace 52 | } 53 | } 54 | return dp[m][n]; 55 | } 56 | 57 | /* Testing Code */ 58 | const str1 = "sunday"; 59 | const str2 = "saturday"; 60 | console.log("Edit distance:", editDist(str1, str2)); 61 | console.log("Edit distance:", editDistDP(str1, str2)); 62 | 63 | /* 64 | Edit distance: 3 65 | Edit distance: 3 66 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/Fibo.js: -------------------------------------------------------------------------------- 1 | function fibonacci(n) { 2 | if (n < 2) 3 | return n; 4 | return fibonacci(n-1) + fibonacci(n-2); 5 | } 6 | 7 | function fibonacciBU2(n) { 8 | if (n < 2) 9 | return n; 10 | 11 | let first = 0; 12 | let second = 1; 13 | let temp = 0; 14 | 15 | for (let i = 2; i <= n; i++) { 16 | temp = first + second; 17 | first = second; 18 | second = temp; 19 | } 20 | return temp; 21 | } 22 | 23 | function fibonacciBU(n) { 24 | if (n < 2) 25 | return n; 26 | 27 | const dp = Array(n+1).fill(0); 28 | dp[0] = 0; 29 | dp[1] = 1; 30 | 31 | for (let i = 2; i <= n; i++) 32 | dp[i] = dp[i-2] + dp[i-1]; 33 | 34 | return dp[n]; 35 | } 36 | 37 | function fibonacciTD(n) { 38 | const dp = Array(n+1).fill(0); 39 | fibonacciTDUtil(n, dp); 40 | return dp[n]; 41 | } 42 | 43 | function fibonacciTDUtil(n, dp) { 44 | if (n < 2) 45 | return dp[n] = n; 46 | 47 | if (dp[n] != 0) 48 | return dp[n]; 49 | 50 | dp[n] = fibonacciTDUtil(n-1, dp) + fibonacciTDUtil(n-2, dp); 51 | return dp[n]; 52 | } 53 | 54 | /* Testing Code */ 55 | console.log(fibonacci(10)); 56 | console.log(fibonacciBU(10)); 57 | console.log(fibonacciBU2(10)); 58 | console.log(fibonacciTD(10)); 59 | 60 | /* 61 | 55 62 | 55 63 | 55 64 | 55 65 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/FloydWarshall.js: -------------------------------------------------------------------------------- 1 | 2 | const INF = Number.MAX_VALUE; 3 | function floydWarshall(graph, V) { 4 | const dist = Array(V).fill(0).map(() => new Array(V).fill(0)); 5 | for (let i = 0; i < V; i++) { 6 | for (let j = 0; j < V; j++) { 7 | dist[i][j] = graph[i][j]; 8 | } 9 | } 10 | // Pick intermediate vertices. 11 | for (let k = 0; k < V; k++) { 12 | // Pick source vertices one by one. 13 | for (let i = 0; i < V; i++) { 14 | // Pick destination vertices. 15 | for (let j = 0; j < V; j++) { 16 | // If we have shorter path from i to j via k. 17 | // then update dist[i][j] 18 | if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) { 19 | dist[i][j] = dist[i][k] + dist[k][j]; 20 | } 21 | } 22 | } 23 | } 24 | // Print the shortest distance matrix 25 | console.log(dist); 26 | } 27 | 28 | /* Testing Code */ 29 | const graph = [ 30 | [0, 2, 4, INF, INF, INF, INF], 31 | [2, 0, 4, 1, INF, INF, INF], 32 | [4, 4, 0, 2, 8, 4, INF], 33 | [INF, 1, 2, 0, 3, INF, 6], 34 | [INF, INF, 6, 4, 0, 3, 1], 35 | [INF, INF, 4, INF, 4, 0, 2], 36 | [INF, INF, INF, 4, 2, 3, 0] 37 | ]; 38 | 39 | floydWarshall(graph, 7); 40 | 41 | /* 42 | [ [ 0, 2, 4, 3, 6, 8, 7 ], 43 | [ 2, 0, 3, 1, 4, 7, 5 ], 44 | [ 4, 3, 0, 2, 5, 4, 6 ], 45 | [ 3, 1, 2, 0, 3, 6, 4 ], 46 | [ 7, 5, 6, 4, 0, 3, 1 ], 47 | [ 8, 7, 4, 6, 4, 0, 2 ], 48 | [ 7, 5, 6, 4, 2, 3, 0 ] ] 49 | */ 50 | -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/GridMinCost.js: -------------------------------------------------------------------------------- 1 | function min(x, y, z) { 2 | x = Math.min(x, y); 3 | return Math.min(x, z); 4 | } 5 | 6 | function minCost(cost, m, n) { 7 | if (m == 0 || n == 0) 8 | return 99999; 9 | 10 | if (m == 1 && n == 1) 11 | return cost[0][0]; 12 | 13 | return cost[m-1][n-1] + min(minCost(cost, m-1, n-1), minCost(cost, m-1, n), minCost(cost, m, n-1)); 14 | } 15 | 16 | function minCostBU(cost, m, n) { 17 | const tc = Array(m).fill(0).map(() => new Array(n).fill(0)); 18 | tc[0][0] = cost[0][0]; 19 | // Initialize first column. 20 | for (let i = 1; i < m; i++) 21 | tc[i][0] = tc[i-1][0] + cost[i][0]; 22 | 23 | // Initialize first row. 24 | for (let j = 1; j < n; j++) 25 | tc[0][j] = tc[0][j-1] + cost[0][j]; 26 | 27 | for (let i = 1; i < m; i++) { 28 | for (let j = 1; j < n; j++) 29 | tc[i][j] = cost[i][j] + min(tc[i-1][j-1], tc[i-1][j], tc[i][j-1]); 30 | } 31 | return tc[m-1][n-1]; 32 | } 33 | 34 | /* Testing Code */ 35 | const cost = [[1, 3, 4], 36 | [4, 7, 5], 37 | [1, 5, 3]]; 38 | console.log(minCost(cost, 3, 3)); 39 | console.log(minCostBU(cost, 3, 3)); 40 | 41 | /* 42 | 11 43 | 11 44 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/GridUniqueWays.js: -------------------------------------------------------------------------------- 1 | 2 | function gridUniqueWays(m, n) { 3 | const dp = Array(m).fill(0).map(() => new Array(n).fill(0)); 4 | dp[0][0] = 1; 5 | // Initialize first column. 6 | for (let i = 1; i < m; i++) 7 | dp[i][0] = dp[i-1][0]; 8 | 9 | // Initialize first row. 10 | for (let j = 1; j < n; j++) 11 | dp[0][j] = dp[0][j-1]; 12 | 13 | for (let i = 1; i < m; i++) { 14 | for (let j = 1; j < n; j++) 15 | dp[i][j] = dp[i-1][j] + dp[i][j-1]; 16 | } 17 | return dp[m-1][n-1]; 18 | } 19 | 20 | // Diagonal movement allowed. 21 | function gridUnique3Ways(m, n) { 22 | const dp = Array(m).fill(0).map(() => new Array(n).fill(0)); 23 | dp[0][0] = 1; 24 | // Initialize first column. 25 | for (let i = 1; i < m; i++) 26 | dp[i][0] = dp[i-1][0]; 27 | 28 | // Initialize first row. 29 | for (let j = 1; j < n; j++) 30 | dp[0][j] = dp[0][j-1]; 31 | 32 | for (let i = 1; i < m; i++) { 33 | for (let j = 1; j < n; j++) 34 | dp[i][j] = dp[i-1][j-1] + dp[i-1][j] + dp[i][j-1]; 35 | } 36 | return dp[m-1][n-1]; 37 | } 38 | 39 | /* Testing Code */ 40 | console.log(gridUniqueWays(3, 3)); 41 | console.log(gridUnique3Ways(3, 3)); 42 | 43 | /* 44 | 6 45 | 13 46 | */ 47 | -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/HouseRobber.js: -------------------------------------------------------------------------------- 1 | function maxRobbery(house) { 2 | const n = house.length; 3 | const dp = Array(n).fill(0); 4 | dp[0] = house[0]; 5 | dp[1] = house[1]; 6 | dp[2] = dp[0] + house[2]; 7 | 8 | for (let i = 3; i < n; i++) 9 | dp[i] = Math.max(dp[i-2], dp[i-3]) + house[i]; 10 | 11 | return Math.max(dp[n-1], dp[n-2]); 12 | } 13 | 14 | function maxRobbery2(house) { 15 | const n = house.length; 16 | const dp = Array(n).fill(0).map(() => new Array(2).fill(0)); 17 | dp[0][1] = house[0]; 18 | dp[0][0] = 0; 19 | for (let i = 1; i < n; ++i) { 20 | dp[i][1] = Math.max(dp[i-1][0] + house[i], dp[i-1][1]); 21 | dp[i][0] = dp[i-1][1]; 22 | } 23 | return Math.max(dp[n-1][1], dp[n-1][0]); 24 | } 25 | 26 | /* Testing Code */ 27 | const arr = [10, 12, 9, 23, 25, 55, 49, 70]; 28 | console.log("Total cash: " + maxRobbery(arr)); 29 | console.log("Total cash: " + maxRobbery2(arr)); 30 | 31 | /* 32 | Total cash: 160 33 | Total cash: 160 34 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/JobScheduling.js: -------------------------------------------------------------------------------- 1 | // Also known as Activity Selection Weighted. 2 | class Job { 3 | constructor(s, f, v) { 4 | this.start = s; 5 | this.stop = f; 6 | this.value = v; 7 | } 8 | } 9 | 10 | function maxValueJobUtil(arr, n) { 11 | // Base case 12 | if (n == 1) 13 | return arr[0].value; 14 | 15 | // Find Value when current job is included 16 | let incl = arr[n-1].value; 17 | for (let j = n-1; j >= 0; j--) { 18 | if (arr[j].stop <= arr[n-1].start) { 19 | incl += maxValueJobUtil(arr, j + 1); 20 | break; 21 | } 22 | } 23 | // Find Value when current job is excluded 24 | let excl = maxValueJobUtil(arr, n-1); 25 | return Math.max(incl, excl); 26 | } 27 | 28 | function maxValueJobs(s, f, v, n) { 29 | const act = Array(n).fill(null); 30 | for (let i = 0; i < n; i++) 31 | act[i] = new Job(s[i], f[i], v[i]); 32 | 33 | // sort according to finish time. 34 | act.sort(function(a, b) { return a.stop - b.stop; }); 35 | 36 | return maxValueJobUtil(act, n); 37 | } 38 | 39 | function maxValueJobUtilTD(dp, arr, n) { 40 | // Base case 41 | if (n == 0) 42 | return 0; 43 | 44 | if (dp[n-1] != 0) 45 | return dp[n-1]; 46 | 47 | // Find Value when current job is included 48 | let incl = arr[n-1].value; 49 | for (let j = n - 2; j >= 0; j--) { 50 | if (arr[j].stop <= arr[n-1].start) { 51 | incl += maxValueJobUtilTD(dp, arr, j + 1); 52 | break; 53 | } 54 | } 55 | // Find Value when current job is excluded 56 | let excl = maxValueJobUtilTD(dp, arr, n-1); 57 | dp[n-1] = Math.max(incl, excl); 58 | return dp[n-1]; 59 | } 60 | 61 | function maxValueJobsTD(s, f, v, n) { 62 | const act = Array(n).fill(null); 63 | for (let i = 0; i < n; i++) 64 | act[i] = new Job(s[i], f[i], v[i]); 65 | 66 | act.sort(function(a, b) {return a.stop - b.stop;} ); // sort according to finish time. 67 | const dp = Array(n).fill(0); 68 | return maxValueJobUtilTD(dp, act, n); 69 | } 70 | 71 | function maxValueJobsBU(s, f, v, n) { 72 | const act = Array(n).fill(null); 73 | for (let i = 0; i < n; i++) 74 | act[i] = new Job(s[i], f[i], v[i]); 75 | 76 | act.sort(function(a, b) {return a.stop - b.stop;}); // sort according to finish time. 77 | const dp = Array(n).fill(0); 78 | dp[0] = act[0].value;; 79 | for (let i = 1; i < n; i++) { 80 | let incl = act[i].value; 81 | for (let j = i-1; j >= 0; j--) { 82 | if (act[j].stop <= act[i].start) { 83 | incl += dp[j]; 84 | break; 85 | } 86 | } 87 | dp[i] = Math.max(incl, dp[i-1]); 88 | } 89 | return dp[n-1]; 90 | } 91 | 92 | /* Testing Code */ 93 | const start = [1, 5, 0, 3, 5, 6, 8]; 94 | const finish = [2, 6, 5, 4, 9, 7, 9]; 95 | const value = [2, 2, 4, 3, 10, 2, 8]; 96 | const n = start.length; 97 | console.log(maxValueJobs(start, finish, value, n)); 98 | console.log(maxValueJobsTD(start, finish, value, n)); 99 | console.log(maxValueJobsBU(start, finish, value, n)); 100 | 101 | /* 102 | 17 103 | 17 104 | 17 105 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/Knapsack.js: -------------------------------------------------------------------------------- 1 | function maxCost01Knapsack(wt, cost, capacity) { 2 | let n = wt.length; 3 | return maxCost01KnapsackUtil(wt, cost, n, capacity); 4 | } 5 | 6 | function maxCost01KnapsackUtil(wt, cost, n, capacity) { 7 | // Base Case 8 | if (n == 0 || capacity == 0) { 9 | return 0; 10 | } 11 | // Return the maximum of two cases: 12 | // (1) nth item is included 13 | // (2) nth item is not included 14 | let first = 0; 15 | if (wt[n-1] <= capacity) 16 | first = cost[n-1] + maxCost01KnapsackUtil(wt, cost, n-1, capacity - wt[n-1]); 17 | 18 | let second = maxCost01KnapsackUtil(wt, cost, n-1, capacity); 19 | return Math.max(first, second); 20 | } 21 | 22 | function maxCost01KnapsackTD(wt, cost, capacity) { 23 | const n = wt.length; 24 | const dp = Array(capacity + 1).fill(0).map(() => new Array(n + 1).fill(0)); 25 | return maxCost01KnapsackTDUtil(dp, wt, cost, n, capacity); 26 | } 27 | 28 | function maxCost01KnapsackTDUtil(dp, wt, cost, i, w) { 29 | if (w == 0 || i == 0) 30 | return 0; 31 | 32 | if (dp[w][i] != 0) 33 | return dp[w][i]; 34 | 35 | // Their are two cases: 36 | // (1) ith item is included 37 | // (2) ith item is not included 38 | let first = 0; 39 | if (wt[i-1] <= w) { 40 | first = maxCost01KnapsackTDUtil(dp, wt, cost, i-1, w - wt[i-1]) + cost[i-1]; 41 | } 42 | let second = maxCost01KnapsackTDUtil(dp, wt, cost, i-1, w); 43 | return dp[w][i] = Math.max(first, second); 44 | } 45 | 46 | function maxCost01KnapsackBU(wt, cost, capacity) { 47 | const n = wt.length; 48 | const dp = Array(capacity + 1).fill(0).map(() => new Array(n + 1).fill(0)); 49 | // Build table dp[][] in bottom up approach. 50 | // Weights considered against capacity. 51 | for (let w = 1; w <= capacity; w++) { 52 | for (let i = 1; i <= n; i++) { 53 | // Their are two cases: 54 | // (1) ith item is included 55 | // (2) ith item is not included 56 | let first = 0; 57 | if (wt[i-1] <= w) { 58 | first = dp[w - wt[i-1]][i-1] + cost[i-1]; 59 | } 60 | let second = dp[w][i-1]; 61 | dp[w][i] = Math.max(first, second); 62 | } 63 | } 64 | printItems(dp, wt, cost, n, capacity); 65 | return dp[capacity][n]; 66 | } 67 | 68 | function printItems(dp, wt, cost, n, capacity) { 69 | let totalCost = dp[capacity][n]; 70 | let output = ""; 71 | for (let i = n-1; i > 0; i--) { 72 | if (totalCost != dp[capacity][i-1]) { 73 | output += " (wt:" + wt[i] + ", cost:" + cost[i] + ")"; 74 | capacity -= wt[i]; 75 | totalCost -= cost[i]; 76 | } 77 | } 78 | console.log("Selected items are:" + output); 79 | } 80 | 81 | function KS01UnboundBU(wt, cost, capacity) { 82 | const n = wt.length; 83 | const dp = Array(capacity + 1).fill(0); 84 | // Build table dp[] in bottom up approach. 85 | // Weights considered against capacity. 86 | for (let w = 1; w <= capacity; w++) { 87 | for (let i = 1; i <= n; i++) { 88 | // Their are two cases: 89 | // (1) ith item is included 90 | // (2) ith item is not included 91 | if (wt[i-1] <= w) { 92 | dp[w] = Math.max(dp[w], dp[w - wt[i-1]] + cost[i-1]); 93 | } 94 | } 95 | } 96 | printItems(dp, wt, cost, n, capacity); 97 | return dp[capacity]; 98 | } 99 | 100 | /* Testing Code */ 101 | const wt = [10, 40, 20, 30]; 102 | const cost = [60, 40, 90, 120]; 103 | const capacity = 50; 104 | let maxCost = maxCost01Knapsack(wt, cost, capacity); 105 | console.log("Maximum cost obtained = " + maxCost); 106 | maxCost = maxCost01KnapsackBU(wt, cost, capacity); 107 | console.log("Maximum cost obtained = " + maxCost); 108 | maxCost = maxCost01KnapsackTD(wt, cost, capacity); 109 | console.log("Maximum cost obtained = " + maxCost); 110 | 111 | /* 112 | Maximum cost obtained = 210 113 | Selected items are: (wt:30, cost:120) (wt:20, cost:90) 114 | Maximum cost obtained = 210 115 | Maximum cost obtained = 210 116 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/LargestBitonicSubseq.js: -------------------------------------------------------------------------------- 1 | function lbs(arr) { 2 | const n = arr.length; 3 | const lis = Array(n).fill(1); // Initialize LIS values for all indexes as 1. 4 | const lds = Array(n).fill(1); // Initialize LDS values for all indexes as 1. 5 | let max = 0; 6 | // Populating LIS values in bottom up manner. 7 | for (let i = 0; i < n; i++) { 8 | for (let j = 0; j < i; j++) { 9 | if (arr[j] < arr[i] && lis[i] < lis[j] + 1) 10 | lis[i] = lis[j] + 1; 11 | } 12 | } 13 | // Populating LDS values in bottom up manner. 14 | for (let i = n-1; i > 0; i--) { 15 | for (let j = n-1; j > i; j--) { 16 | if (arr[j] < arr[i] && lds[i] < lds[j] + 1) 17 | lds[i] = lds[j] + 1; 18 | } 19 | } 20 | for (let i = 0; i < n; i++) 21 | max = Math.max(max, lis[i] + lds[i]-1); 22 | 23 | return max; 24 | } 25 | 26 | /* Testing Code */ 27 | const arr = [1, 6, 3, 11, 1, 9, 5, 12, 3, 14, 6, 17, 3, 19, 2, 19]; 28 | console.log("Length of lis is " + lbs(arr)); 29 | 30 | /* 31 | Length of lis is 8 32 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/LargestIncreasingSubseq.js: -------------------------------------------------------------------------------- 1 | function lis(arr) { 2 | const n = arr.length; 3 | const lis = Array(n).fill(0); 4 | let max = 0; 5 | // Populating LIS values in bottom up manner. 6 | for (let i = 0; i < n; i++) { 7 | lis[i] = 1; 8 | // Initialize LIS values for all indexes as 1. 9 | for (let j = 0; j < i; j++) { 10 | if (arr[j] < arr[i] && lis[i] < lis[j] + 1) 11 | lis[i] = lis[j] + 1; 12 | } 13 | 14 | if (max < lis[i]) // Max LIS values. 15 | max = lis[i]; 16 | } 17 | return max; 18 | } 19 | 20 | /* Testing Code */ 21 | const arr = [10, 12, 9, 23, 25, 55, 49, 70]; 22 | console.log("Length of lis is " + lis(arr)); 23 | 24 | /* 25 | Length of lis is 6 26 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/LargestPalindromicSubsequence.js: -------------------------------------------------------------------------------- 1 | function palindromicSubsequence(str) { 2 | const n = str.length; 3 | const dp = Array(n).fill(0).map(() => new Array(n).fill(0)); 4 | for (let i = 0; i < n; i++) // each char is itself palindromic with length 1 5 | dp[i][i] = 1; 6 | 7 | 8 | for (let l = 1; l < n; l++) { 9 | for (let i = 0, j = l; j < n; i++, j++) { 10 | if (str.charAt(i) == str.charAt(j)) 11 | dp[i][j] = dp[i + 1][j - 1] + 2; 12 | else 13 | dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); 14 | } 15 | } 16 | return dp[0][n - 1]; 17 | } 18 | 19 | /* Testing Code */ 20 | const str = "ABCAUCBCxxCBA"; 21 | console.log("Max Palindromic Subsequence length: " + palindromicSubsequence(str)); 22 | 23 | /* 24 | Max Palindromic Subsequence length: 9 25 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/LargestPalindromicSubstr.js: -------------------------------------------------------------------------------- 1 | 2 | function palindromicSubstring(str) { 3 | const n = str.length; 4 | const dp = Array(n).fill(0).map(() => new Array(n).fill(0)); 5 | for (let i = 0; i < n; i++) 6 | dp[i][i] = 1; 7 | 8 | let max = 1; 9 | let start = 0; 10 | for (let l = 1; l < n; l++) { 11 | for (let i = 0, j = i + l; j < n; i++, j++) { 12 | if (str.charAt(i) == str.charAt(j) && dp[i+1][j-1] == j-i-1) { 13 | dp[i][j] = dp[i + 1][j-1] + 2; 14 | if (dp[i][j] > max) { 15 | max = dp[i][j]; // Keeping track of max length 16 | start = i; 17 | } 18 | } else { 19 | dp[i][j] = 0; 20 | } 21 | } 22 | } 23 | console.log("Max Length Palindromic Substrings : " +str.substring(start, start + max)); 24 | return max; 25 | } 26 | 27 | /* Testing Code */ 28 | const str = "ABCAUCBCxxCBA"; 29 | console.log("Max Palindromic Substrings len: " + palindromicSubstring(str)); 30 | 31 | /* 32 | Max Length Palindromic Substrings : BCxxCB 33 | Max Palindromic Substrings len: 6 34 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/LongestCommonSubseq.js: -------------------------------------------------------------------------------- 1 | function LCSubStr(st1, st2) { 2 | let X = st1.split(''); 3 | let Y = st2.split(''); 4 | const m = st1.length; 5 | const n = st2.length; 6 | const dp = Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0)); // Dynamic programming array. 7 | const p = Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0)); // For printing the substring. 8 | 9 | // Fill dp array in bottom up fashion. 10 | for (let i = 1; i <= m; i++) { 11 | for (let j = 1; j <= n; j++) { 12 | if (X[i-1] == Y[j-1]) { 13 | dp[i][j] = dp[i-1][j-1] + 1; 14 | p[i][j] = 0; 15 | } else { 16 | dp[i][j] = (dp[i-1][j] > dp[i][j-1]) ? dp[i-1][j] : dp[i][j-1]; 17 | p[i][j] = (dp[i-1][j] > dp[i][j-1]) ? 1 : 2; 18 | } 19 | } 20 | } 21 | PrintLCS(p, X, m, n); 22 | return dp[m][n]; 23 | } 24 | 25 | function PrintLCS(p, X, i, j) { 26 | console.log(PrintLCSUtil(p, X, i, j)) 27 | } 28 | 29 | function PrintLCSUtil(p, X, i, j) { 30 | if (i == 0 || j == 0) 31 | return ""; 32 | let output = ""; 33 | if (p[i][j] == 0) { 34 | output = PrintLCSUtil(p, X, i-1, j-1); 35 | output += X[i-1]; 36 | } 37 | else if (p[i][j] == 1) { 38 | output = PrintLCSUtil(p, X, i-1, j); 39 | } 40 | else 41 | { 42 | output = PrintLCSUtil(p, X, i, j-1); 43 | } 44 | return output; 45 | } 46 | 47 | /* Testing Code */ 48 | const X = "carpenter"; 49 | const Y = "sharpener"; 50 | console.log("LCSubStr length: " + LCSubStr(X, Y)); 51 | 52 | /* 53 | arpener 54 | LCSubStr : 7 55 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/MatrixCM.js: -------------------------------------------------------------------------------- 1 | 2 | function MatrixChainMulBruteForceUtil(p, i, j) { 3 | if (i == j) { 4 | return 0; 5 | } 6 | let min = Number.MAX_VALUE; 7 | // place parenthesis at different places between 8 | // first and last matrix, recursively calculate 9 | // count of multiplications for each parenthesis 10 | // placement and return the minimum count 11 | for (let k = i; k < j; k++) { 12 | let count = MatrixChainMulBruteForceUtil(p, i, k) + 13 | MatrixChainMulBruteForceUtil(p, k+1, j) + p[i-1] * p[k] * p[j]; 14 | min = Math.min(min, count); 15 | } 16 | // Return minimum count 17 | return min; 18 | } 19 | 20 | function MatrixChainMulBruteForce(p, n) { 21 | let i = 1, j = n-1; 22 | return MatrixChainMulBruteForceUtil(p, i, j); 23 | } 24 | 25 | function MatrixChainMulTD(p, n) { 26 | const dp = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 27 | for (let i = 1; i < n; i++) 28 | dp[i][i] = 0; 29 | 30 | return MatrixChainMulTDUtil(dp, p, 1, n-1); 31 | } 32 | 33 | function MatrixChainMulTDUtil(dp, p, i, j) { 34 | // Base Case 35 | if (dp[i][j] != Number.MAX_VALUE) { 36 | return dp[i][j]; 37 | } 38 | for (let k = i; k < j; k++) { 39 | dp[i][j] = Math.min(dp[i][j], MatrixChainMulTDUtil(dp, p, i, k) + 40 | MatrixChainMulTDUtil(dp, p, k+1, j) + p[i-1]*p[k]*p[j]); 41 | } 42 | return dp[i][j]; 43 | } 44 | 45 | function MatrixChainMulBU(p, n) { 46 | const dp = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 47 | 48 | for (let i = 1; i < n; i++) { 49 | dp[i][i] = 0; 50 | } 51 | 52 | for (let l = 1; l < n; l++) { // l is length of range. 53 | for (let i = 1, j = i + l; j < n; i++, j++) { 54 | for (let k = i; k < j; k++) { 55 | dp[i][j] = Math.min(dp[i][j], dp[i][k] + p[i-1]*p[k]*p[j] + dp[k+1][j]); 56 | } 57 | } 58 | } 59 | return dp[1][n-1]; 60 | } 61 | 62 | function MatrixChainMulBU2(p, n) { 63 | const dp = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 64 | const pos = Array(n).fill(0).map(() => new Array(n)); 65 | for (let i = 1; i < n; i++) { 66 | dp[i][i] = 0; 67 | pos[i][i] = i; 68 | } 69 | for (let l = 1; l < n; l++) { // l is length of range. 70 | for (let i = 1, j = i + l; j < n; i++, j++) { 71 | for (let k = i; k < j; k++) { 72 | dp[i][j] = Math.min(dp[i][j], dp[i][k] + p[i-1]*p[k]*p[j] + dp[k+1][j]); 73 | pos[i][j] = k; 74 | } 75 | } 76 | } 77 | PrintOptimalParenthesis(n, pos); 78 | return dp[1][n-1]; 79 | } 80 | 81 | function PrintOptimalParenthesis(n, pos) { 82 | console.log("OptimalParenthesis : " + PrintOptPar(n, pos, 1, n-1)); 83 | }; 84 | 85 | function PrintOptPar(n, pos, i, j) { 86 | let output = ""; 87 | if (i === j) 88 | output += "M" + pos[i][i] + " "; 89 | else { 90 | output += "( "; 91 | output += PrintOptPar(n, pos, i, pos[i][j]); 92 | output += PrintOptPar(n, pos, pos[i][j]+1, j); 93 | output += ") "; 94 | } 95 | return output; 96 | }; 97 | 98 | /* Testing Code */ 99 | const arr = [1, 2, 3, 4]; 100 | const n = arr.length; 101 | console.log("Matrix Chain Multiplication is:" + MatrixChainMulBruteForce(arr, n)); 102 | console.log("Matrix Chain Multiplication is:" + MatrixChainMulTD(arr, n)); 103 | console.log("Matrix Chain Multiplication is:" + MatrixChainMulBU(arr, n)); 104 | console.log("Matrix Chain Multiplication is:" + MatrixChainMulBU2(arr, n)); 105 | 106 | 107 | /* 108 | Matrix Chain Multiplication is:18 109 | Matrix Chain Multiplication is:18 110 | Matrix Chain Multiplication is:18 111 | OptimalParenthesis : ( ( M1 M2 ) M3 ) 112 | Matrix Chain Multiplication is:18 113 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/MinCostBinaryTree.js: -------------------------------------------------------------------------------- 1 | function maxVal(max, i, j) { 2 | if (max[i][j] != Number.MIN_VALUE) { 3 | return max[i][j]; 4 | } 5 | 6 | for (let k = i; k < j; k++) { 7 | max[i][j] = Math.max(max[i][j], Math.max(maxVal(max, i, k), maxVal(max, k+1, j))); 8 | } 9 | 10 | return max[i][j]; 11 | } 12 | 13 | function minCostBstTDUtil(dp, max, i, j, arr) { 14 | if (j <= i) { 15 | return 0; 16 | } 17 | 18 | if (dp[i][j] != Number.MAX_VALUE) { 19 | return dp[i][j]; 20 | } 21 | 22 | for (let k = i; k < j; k++) { 23 | dp[i][j] = Math.min(dp[i][j], minCostBstTDUtil(dp, max, i, k, arr) + 24 | minCostBstTDUtil(dp, max, k+1, j, arr) + maxVal(max, i, k) * maxVal(max, k+1, j)); 25 | } 26 | 27 | return dp[i][j]; 28 | } 29 | 30 | function minCostBstTD(arr) { 31 | const n = arr.length; 32 | const dp = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 33 | const max = Array(n).fill(0).map(() => new Array(n).fill(Number.MIN_VALUE)); 34 | 35 | for (let i = 0; i < n; i++) 36 | max[i][i] = arr[i]; 37 | 38 | return minCostBstTDUtil(dp, max, 0, n - 1, arr); 39 | } 40 | 41 | function minCostBstBU(arr) { 42 | const n = arr.length; 43 | const dp = Array(n).fill(0).map(() => new Array(n).fill(0)); 44 | const max = Array(n).fill(0).map(() => new Array(n).fill(0)); 45 | for (let i = 0; i < n; i++) 46 | max[i][i] = arr[i]; 47 | 48 | for (let l = 1; l < n; l++) { 49 | // l is length of range. 50 | for (let i = 0, j = i + l; j < n; i++, j++) { 51 | dp[i][j] = Number.MAX_VALUE; 52 | for (let k = i; k < j; k++) { 53 | dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k+1][j] + max[i][k] * max[k+1][j]); 54 | max[i][j] = Math.max(max[i][k], max[k+1][j]); 55 | } 56 | } 57 | } 58 | 59 | return dp[0][n - 1]; 60 | } 61 | 62 | /* Testing Code */ 63 | const arr = [6, 2, 4]; 64 | console.log("Total cost: " + minCostBstTD(arr)); 65 | console.log("Total cost: " + minCostBstBU(arr)); 66 | 67 | /* 68 | Total cost: 32 69 | Total cost: 32 70 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/MinStairCost.js: -------------------------------------------------------------------------------- 1 | 2 | function minStairCost(cost) { 3 | const n = a.length; 4 | 5 | // base case 6 | if (n == 1) 7 | return cost[0]; 8 | 9 | const dp = Array(n).fill(0); 10 | dp[0] = cost[0]; 11 | dp[1] = cost[1]; 12 | for (let i = 2; i < n; i++) 13 | dp[i] = Math.min(dp[i - 1], dp[i - 2]) + cost[i]; 14 | 15 | return Math.min(dp[n - 2], dp[n - 1]); 16 | } 17 | 18 | /* Testing Code */ 19 | const a = [1, 5, 6, 3, 4, 7, 9, 1, 2, 11]; 20 | console.log("minStairCost :", minStairCost(a)); 21 | 22 | /* 23 | minStairCost : 18 24 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/OptimalBST.js: -------------------------------------------------------------------------------- 1 | function optCostUtil(freq, i, j) { 2 | if (i > j) 3 | return 0; 4 | 5 | if (j == i) // one element in this subarray 6 | return freq[i]; 7 | 8 | let min = Number.MAX_VALUE; 9 | for (let r = i; r <= j; r++) { 10 | min = Math.min(min, optCostUtil(freq, i, r-1) + optCostUtil(freq, r+1, j)); 11 | } 12 | return min + sum(freq, i, j); 13 | } 14 | 15 | function optCost(keys, freq) { 16 | const n = freq.length; 17 | return optCostUtil(freq, 0, n-1); 18 | } 19 | 20 | function optCostTD(keys, freq) { 21 | const n = freq.length; 22 | const cost = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 23 | for (let i = 0; i < n; i++) { 24 | cost[i][i] = freq[i]; 25 | } 26 | return optCostTDUtil(freq, cost, 0, n-1); 27 | } 28 | 29 | function optCostTDUtil(freq, cost, i, j) { 30 | if (i > j) 31 | return 0; 32 | 33 | if (cost[i][j] != Number.MAX_VALUE) 34 | return cost[i][j]; 35 | 36 | let s = sum(freq, i, j); 37 | for (let r = i; r <= j; r++) { 38 | cost[i][j] = Math.min(cost[i][j], optCostTDUtil(freq, cost, i, r-1) + 39 | optCostTDUtil(freq, cost, r+1, j) + s); 40 | } 41 | return cost[i][j]; 42 | } 43 | 44 | function sum(freq, i, j) { 45 | let s = 0; 46 | for (let k = i; k <= j; k++) 47 | s += freq[k]; 48 | return s; 49 | } 50 | 51 | function sumInit(freq, n) { 52 | const sum = Array(n).fill(0); 53 | sum[0] = freq[0]; 54 | for (let i = 1; i < n; i++) 55 | sum[i] = sum[i-1] + freq[i]; 56 | return sum; 57 | } 58 | 59 | function sumRange(sum, i, j) { 60 | if (i == 0) 61 | return sum[j]; 62 | return sum[j] - sum[i-1]; 63 | } 64 | 65 | function optCostBU(keys, freq) { 66 | const n = freq.length; 67 | const cost = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 68 | for (let i = 0; i < n; i++) 69 | cost[i][i] = freq[i]; 70 | 71 | let sm = 0; 72 | for (let l = 1; l < n; l++) { // l is length of range. 73 | for (let i = 0, j = i + l; j < n; i++, j++) { 74 | sm = sum(freq, i, j); 75 | for (let r = i; r <= j; r++) { 76 | cost[i][j] = Math.min(cost[i][j], sm + ((r-1 >= i) ? cost[i][r-1] : 0) + ((r+1 <= j) ? cost[r+1][j] : 0)); 77 | } 78 | } 79 | } 80 | return cost[0][n-1]; 81 | } 82 | 83 | function optCostBU2(keys, freq) { 84 | const n = freq.length; 85 | const cost = Array(n).fill(0).map(() => new Array(n).fill(Number.MAX_VALUE)); 86 | let sumArr = sumInit(freq, n); 87 | for (let i = 0; i < n; i++) 88 | cost[i][i] = freq[i]; 89 | 90 | let sm = 0; 91 | for (let l = 1; l < n; l++) { // l is length of range. 92 | for (let i = 0, j = i + l; j < n; i++, j++) { 93 | sm = sumRange(sumArr, i, j); 94 | for (let r = i; r <= j; r++) { 95 | cost[i][j] = Math.min(cost[i][j], sm + ((r-1 >= i) ? cost[i][r-1] : 0) + ((r+1 <= j) ? cost[r+1][j] : 0)); 96 | } 97 | } 98 | } 99 | return cost[0][n-1]; 100 | } 101 | 102 | /* Testing Code */ 103 | const keys = [9, 15, 25]; 104 | const freq = [30, 10, 40]; 105 | console.log("OBST cost:" + optCost(keys, freq)); 106 | console.log("OBST cost:" + optCostTD(keys, freq)); 107 | console.log("OBST cost:" + optCostBU(keys, freq)); 108 | console.log("OBST cost:" + optCostBU2(keys, freq)); 109 | 110 | /* 111 | OBST cost:130 112 | OBST cost:130 113 | OBST cost:130 114 | OBST cost:130 115 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/StairUniqueWays.js: -------------------------------------------------------------------------------- 1 | function stairUniqueWaysBU(n) { 2 | if (n <= 2) 3 | return n; 4 | 5 | let first = 1, second = 2, temp = 0; 6 | for (let i = 3; i <= n; i++) { 7 | temp = first + second; 8 | first = second; 9 | second = temp; 10 | } 11 | return temp; 12 | } 13 | 14 | function stairUniqueWaysBU2(n) { 15 | if (n < 2) 16 | return n; 17 | 18 | const ways = Array(n).fill(0); 19 | ways[0] = 1; 20 | ways[1] = 2; 21 | for (let i = 2; i < n; i++) 22 | ways[i] = ways[i-1] + ways[i - 2]; 23 | return ways[n-1]; 24 | } 25 | 26 | /* Testing Code */ 27 | console.log("Unique way to reach top:: " + stairUniqueWaysBU(4)); 28 | console.log("Unique way to reach top:: " + stairUniqueWaysBU2(4)); 29 | 30 | /* 31 | Unique way to reach top:: 5 32 | Unique way to reach top:: 5 33 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/StockBuySell.js: -------------------------------------------------------------------------------- 1 | function maxProfit(arr) { 2 | let buyProfit = -arr[0]; // Buy stock profit 3 | let sellProfit = 0; // Sell stock profit 4 | const n = arr.length; 5 | for (let i = 1; i < n; i++) { 6 | let newBuyProfit = (sellProfit - arr[i] > buyProfit) ? sellProfit - arr[i] : buyProfit; 7 | let newSellProfit = (buyProfit + arr[i] > sellProfit) ? buyProfit + arr[i] : sellProfit; 8 | buyProfit = newBuyProfit; 9 | sellProfit = newSellProfit; 10 | } 11 | return sellProfit; 12 | } 13 | 14 | function maxProfitTC(arr, t) { 15 | let buyProfit = -arr[0]; 16 | let sellProfit = 0; 17 | const n = arr.length; 18 | for (let i = 1; i < n; i++) { 19 | let newBuyProfit = ((sellProfit - arr[i]) > buyProfit) ? (sellProfit - arr[i]) : buyProfit; 20 | let newSellProfit = ((buyProfit + arr[i] - t) > sellProfit) ? (buyProfit + arr[i] - t) : sellProfit; 21 | buyProfit = newBuyProfit; 22 | sellProfit = newSellProfit; 23 | } 24 | return sellProfit; 25 | } 26 | 27 | function maxProfit2(arr) { 28 | const n = arr.length; 29 | const dp = Array(n).fill(0).map(() => new Array(2).fill(0)); 30 | dp[0][0] = -arr[0]; // Buy stock profit 31 | dp[0][1] = 0; // Sell stock profit 32 | for (let i = 1; i < n; i++) { 33 | dp[i][0] = (dp[i-1][1] - arr[i] > dp[i-1][0]) ? dp[i-1][1] - arr[i] : dp[i-1][0]; 34 | dp[i][1] = (dp[i-1][0] + arr[i] > dp[i-1][1]) ? dp[i-1][0] + arr[i] : dp[i-1][1]; 35 | } 36 | return dp[n-1][1]; 37 | } 38 | 39 | function maxProfitTC2(arr, t) { 40 | const n = arr.length; 41 | const dp = Array(n).fill(0).map(() => new Array(2).fill(0)); 42 | dp[0][0] = -arr[0]; 43 | dp[0][1] = 0; 44 | for (let i = 1; i < n; i++) { 45 | dp[i][0] = ((dp[i-1][1] - arr[i]) > dp[i-1][0]) ? (dp[i-1][1] - arr[i]) : dp[i-1][0]; 46 | dp[i][1] = ((dp[i-1][0] + arr[i] - t) > dp[i-1][1]) ? (dp[i-1][0] + arr[i] - t) : dp[i-1][1]; 47 | } 48 | return dp[n-1][1]; 49 | } 50 | 51 | /* Testing Code */ 52 | const arr = [10, 12, 9, 23, 25, 55, 49, 70]; 53 | console.log("Total profit: " + maxProfit(arr)); 54 | console.log("Total profit: " + maxProfit2(arr)); 55 | console.log("Total profit: " + maxProfitTC(arr, 2)); 56 | console.log("Total profit: " + maxProfitTC2(arr, 2)); 57 | 58 | /* 59 | Total profit: 69 60 | Total profit: 69 61 | Total profit: 63 62 | Total profit: 63 63 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/Vacation.js: -------------------------------------------------------------------------------- 1 | 2 | // days are must travel days, costs are cost of tickets. 3 | function minCostVacation(days, costs) { 4 | const n = days.length; 5 | let max = days[n - 1]; 6 | const dp = Array(max + 1).fill(0); 7 | let j = 0; 8 | for (let i = 1; i <= max; i++) { 9 | if (days[j] == i) { 10 | // That days is definitely travelled. 11 | j++; 12 | dp[i] = dp[i - 1] + costs[0]; 13 | dp[i] = Math.min(dp[i], dp[Math.max(0, i - 7)] + costs[1]); 14 | dp[i] = Math.min(dp[i], dp[Math.max(0, i - 30)] + costs[2]); 15 | } else { 16 | dp[i] = dp[i - 1]; 17 | } 18 | } 19 | return dp[max]; 20 | } 21 | 22 | /* Testing Code */ 23 | const days = [1, 3, 5, 7, 12, 20, 30]; 24 | const costs = [2, 7, 20]; 25 | console.log("Min cost is:" + minCostVacation(days, costs)); 26 | 27 | /* 28 | Min cost is:13 29 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/DP/WildCharMatch.js: -------------------------------------------------------------------------------- 1 | function wildCharMatchExp(exp, str) { 2 | return wildCharMatchExpUtil(exp.split(''), str.split(''), 0, 0); 3 | } 4 | 5 | function wildCharMatchExpUtil(exp, str, m, n) { 6 | if (m == exp.length && (n == str.length || exp[m-1] == '*')) 7 | return true; 8 | 9 | if ((m == exp.length && n != str.length) || (m != exp.length && n == str.length)) 10 | return false; 11 | 12 | if (exp[m] == '?' || exp[m] == str[n]) 13 | return wildCharMatchExpUtil(exp, str, m + 1, n + 1); 14 | 15 | if (exp[m] == '*') 16 | return wildCharMatchExpUtil(exp, str, m + 1, n) || wildCharMatchExpUtil(exp, str, m, n + 1); 17 | 18 | return false; 19 | } 20 | 21 | function wildCharMatchExpDP(exp, str) { 22 | return wildCharMatchExpDPUtil(exp.split(''), str.split(''), exp.length, str.length); 23 | } 24 | 25 | function wildCharMatchExpDPUtil(exp, str, m, n) { 26 | const lookup = Array(m + 1).fill(false).map(() => new Array(n + 1).fill(false)); 27 | lookup[0][0] = true; // empty exp and empty str match. 28 | 29 | // 0 row will remain all false. empty exp can't match any str. 30 | // '*' can match with empty string, column 0 update. 31 | for (let i = 1; i <= m; i++) { 32 | if (exp[i-1] == '*') 33 | lookup[i][0] = lookup[i-1][0]; 34 | else 35 | break; 36 | } 37 | 38 | // Fill the table in bottom-up fashion 39 | for (let i = 1; i <= m; i++) { 40 | for (let j = 1; j <= n; j++) { 41 | // If we see a '*' in pattern: 42 | // 1) We ignore '*' character and consider 43 | // next character in the pattern. 44 | // 2) We ignore one character in the input str 45 | // and consider next character. 46 | if (exp[i-1] == '*') 47 | lookup[i][j] = lookup[i-1][j] || lookup[i][j-1]; 48 | // Condition when both the pattern and input string 49 | // have same character. Also '?' match with all the 50 | // characters. 51 | else if (exp[i-1] == '?' || str[j-1] == exp[i-1]) 52 | lookup[i][j] = lookup[i-1][j-1]; 53 | // If characters don't match 54 | else 55 | lookup[i][j] = false; 56 | } 57 | } 58 | return lookup[m][n]; 59 | } 60 | 61 | /* Testing Code */ 62 | console.log(wildCharMatchExp("*llo,?World?", "Hello, World!")); 63 | console.log(wildCharMatchExpDP("*llo,?World?", "Hello, World!")); 64 | 65 | /* 66 | true 67 | true 68 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/ActivitySelection.js: -------------------------------------------------------------------------------- 1 | // Prints a maximum set of activities that can be done by a 2 | // single person performing one task at a time. 3 | // s[] is an array that contains start time of all activities 4 | // f[] is an array that contains finish time of all activities 5 | 6 | class Activity { 7 | constructor(s, f) { 8 | this.start = s; 9 | this.stop = f; 10 | } 11 | } 12 | 13 | function maxActivities(s, f, n) { 14 | const act = Array(n).fill(0); 15 | for (let i = 0; i < n; i++) 16 | act[i] = new Activity(s[i], f[i]); 17 | 18 | act.sort(function(a, b) {return a.stop - b.stop;}); // sort according to finish time. 19 | let i = 0; 20 | // The first activity at index 0 is always gets selected. 21 | let output = "Activities are : (" + act[i].start + "," + act[i].stop + ")"; 22 | for (let j = 1; j < n; j++) { 23 | // Find next activity whose start time is greater than or equal 24 | // to the finish time of previous activity. 25 | if (act[j].start >= act[i].stop) { 26 | output += ", (" + act[j].start + "," + act[j].stop + ")"; 27 | i = j; 28 | } 29 | } 30 | console.log(output) 31 | } 32 | 33 | /* Testing Code */ 34 | const s = [1, 5, 0, 3, 5, 6, 8]; 35 | const f = [2, 6, 5, 4, 9, 7, 9]; 36 | const n = s.length; 37 | maxActivities(s, f, n); 38 | 39 | /* 40 | Activities are : (1,2), (3,4), (5,6), (6,7), (8,9) 41 | */ 42 | -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/ChotaBhim.js: -------------------------------------------------------------------------------- 1 | 2 | greater = (x, y) => (x > y); 3 | less = (x, y) => (x < y); 4 | 5 | class PriorityQueue { 6 | constructor(cmp) { 7 | this.comp = cmp; 8 | this.size = 0; 9 | this.arr = []; 10 | } 11 | 12 | /* Other methods */ 13 | percolateDown(parent) { 14 | const lChild = 2 * parent + 1; 15 | const rChild = lChild + 1; 16 | let child = -1; 17 | let temp; 18 | if (lChild <= this.size) { 19 | child = lChild; 20 | } 21 | if (rChild <= this.size && this.comp(this.arr[lChild], this.arr[rChild])) { 22 | child = rChild; 23 | } 24 | if (child !== -1 && this.comp(this.arr[parent], this.arr[child])) { 25 | temp = this.arr[parent]; 26 | this.arr[parent] = this.arr[child]; 27 | this.arr[child] = temp; 28 | this.percolateDown(child); 29 | } 30 | } 31 | 32 | percolateUp(child) { 33 | const parent = Math.floor((child - 1) / 2); 34 | if (parent < 0) { 35 | return; 36 | } 37 | if (this.comp(this.arr[parent], this.arr[child])) { 38 | const temp = this.arr[child]; 39 | this.arr[child] = this.arr[parent]; 40 | this.arr[parent] = temp; 41 | this.percolateUp(parent); 42 | } 43 | } 44 | 45 | add(value) { 46 | this.arr[this.size] = value; 47 | this.size += 1; 48 | this.percolateUp(this.size - 1); 49 | } 50 | 51 | remove() { 52 | if (this.isEmpty()) { 53 | throw new Error("IllegalStateException"); 54 | } 55 | const value = this.arr[0]; 56 | this.arr[0] = this.arr[this.size - 1]; 57 | this.size--; 58 | this.percolateDown(0); 59 | return value; 60 | } 61 | 62 | print() { 63 | console.log(this.arr); 64 | } 65 | 66 | isEmpty() { 67 | return (this.size === 0); 68 | } 69 | 70 | length() { 71 | return this.size; 72 | } 73 | 74 | peek() { 75 | if (this.isEmpty()) { 76 | throw new Error("IllegalStateException"); 77 | } 78 | return this.arr[0] 79 | } 80 | } 81 | 82 | function chotaBhim(cups) { 83 | const size = cups.length; 84 | let time = 60; 85 | cups.sort(function(a, b){return b - a;}); 86 | let total = 0, index = 0, temp = 0; 87 | while (time > 0) { 88 | total += cups[0]; 89 | cups[0] = parseInt(Math.ceil(cups[0] / 2.0)); 90 | index = 0; 91 | temp = cups[0]; 92 | while (index < size - 1 && temp < cups[index + 1]) { 93 | cups[index] = cups[index + 1]; 94 | index += 1; 95 | } 96 | cups[index] = temp; 97 | time -= 1; 98 | } 99 | console.log("Total : " + total); 100 | return total; 101 | } 102 | 103 | function chotaBhim2(cups) { 104 | const size = cups.length; 105 | let time = 60; 106 | let pq = new PriorityQueue(less); 107 | for (let i = 0; i < size; i++) { 108 | pq.add(cups[i]); 109 | } 110 | let total = 0; 111 | let value = 0; 112 | while (time > 0) { 113 | value = pq.remove(); 114 | total += value; 115 | value = Math.ceil(value / 2.0); 116 | pq.add(value); 117 | time -= 1; 118 | } 119 | console.log("Total : " + total); 120 | return total; 121 | } 122 | 123 | /* Testing Code */ 124 | const cups = [2, 1, 7, 4, 2]; 125 | chotaBhim(cups); 126 | const cups2 = [2, 1, 7, 4, 2]; 127 | chotaBhim2(cups2); 128 | 129 | /* 130 | Total : 76 131 | Total : 76 132 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/FractionalKnapsack.js: -------------------------------------------------------------------------------- 1 | 2 | class Items { 3 | constructor(w, v) { 4 | this.wt = w; 5 | this.cost = v; 6 | this.density = v / w; 7 | } 8 | } 9 | 10 | function getMaxCostFractional(wt, cost, capacity) { 11 | let totalCost = 0; 12 | const n = wt.length; 13 | const itemList = Array(n).fill(null); 14 | 15 | for (let i = 0; i < n; i++) { 16 | itemList[i] = new Items(wt[i], cost[i]); 17 | } 18 | itemList.sort(function(a, b){return b.density - a.density;}); // decreasing order. 19 | for (let i = 0; i < n; i++) { 20 | if (capacity - itemList[i].wt >= 0) { 21 | capacity -= itemList[i].wt; 22 | totalCost += itemList[i].cost; 23 | } 24 | else 25 | { 26 | totalCost += (itemList[i].density * capacity); 27 | break; 28 | } 29 | } 30 | return totalCost; 31 | } 32 | 33 | /* Testing Code */ 34 | const wt = [10, 40, 20, 30]; 35 | const cost = [60, 40, 90, 120]; 36 | const capacity = 50; 37 | let maxCost = getMaxCostFractional(wt, cost, capacity); 38 | console.log("Maximum cost obtained = " + maxCost); 39 | 40 | /* 41 | Maximum cost obtained = 230 42 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/HuffmanTree.js: -------------------------------------------------------------------------------- 1 | greater = (x, y) => (x > y); 2 | less = (x, y) => (x < y); 3 | 4 | class PriorityQueue { 5 | constructor(cmp) { 6 | this.comp = cmp; 7 | this.size = 0; 8 | this.arr = []; 9 | } 10 | 11 | /* Other methods */ 12 | percolateDown(parent) { 13 | const lChild = 2 * parent + 1; 14 | const rChild = lChild + 1; 15 | let child = -1; 16 | let temp; 17 | if (lChild <= this.size) { 18 | child = lChild; 19 | } 20 | if (rChild <= this.size && this.comp(this.arr[lChild], this.arr[rChild])) { 21 | child = rChild; 22 | } 23 | if (child !== -1 && this.comp(this.arr[parent], this.arr[child])) { 24 | temp = this.arr[parent]; 25 | this.arr[parent] = this.arr[child]; 26 | this.arr[child] = temp; 27 | this.percolateDown(child); 28 | } 29 | } 30 | 31 | percolateUp(child) { 32 | const parent = Math.floor((child - 1) / 2); 33 | if (parent < 0) { 34 | return; 35 | } 36 | if (this.comp(this.arr[parent], this.arr[child])) { 37 | const temp = this.arr[child]; 38 | this.arr[child] = this.arr[parent]; 39 | this.arr[parent] = temp; 40 | this.percolateUp(parent); 41 | } 42 | } 43 | 44 | add(value) { 45 | this.arr[this.size] = value; 46 | this.size += 1; 47 | this.percolateUp(this.size - 1); 48 | } 49 | 50 | remove() { 51 | if (this.isEmpty()) { 52 | throw new Error("IllegalStateException"); 53 | } 54 | const value = this.arr[0]; 55 | this.arr[0] = this.arr[this.size - 1]; 56 | this.size--; 57 | this.percolateDown(0); 58 | return value; 59 | } 60 | 61 | print() { 62 | console.log(this.arr); 63 | } 64 | 65 | isEmpty() { 66 | return (this.size === 0); 67 | } 68 | 69 | length() { 70 | return this.size; 71 | } 72 | 73 | peek() { 74 | if (this.isEmpty()) { 75 | throw new Error("IllegalStateException"); 76 | } 77 | return this.arr[0] 78 | } 79 | } 80 | 81 | class Node { 82 | constructor(ch, fr, l, r) { 83 | this.c = ch; 84 | this.freq = fr; 85 | this.left = l; 86 | this.right = r; 87 | } 88 | } 89 | 90 | class HuffmanTree { 91 | constructor(arr, freq) { 92 | const n = arr.length; 93 | const que = new PriorityQueue(function(a, b){return (a.freq - b.freq) > 0 }); 94 | 95 | for (let i = 0; i < n; i++) { 96 | let node = new Node(arr[i], freq[i], null, null); 97 | que.add(node); 98 | } 99 | 100 | while (que.length() > 1) { 101 | let lt = que.remove(); 102 | let rt = que.remove(); 103 | let nd = new Node('+', lt.freq + rt.freq, lt, rt); 104 | que.add(nd); 105 | } 106 | this.root = que.peek(); 107 | } 108 | 109 | printUtil(root, s) { 110 | if (root.left == null && root.right == null && root.c != '+') { 111 | console.log(root.c + " = " + s); 112 | return; 113 | } 114 | this.printUtil(root.left, s + "0"); 115 | this.printUtil(root.right, s + "1"); 116 | } 117 | 118 | print() { 119 | console.log("Char = Huffman code"); 120 | this.printUtil(this.root, ""); 121 | } 122 | } 123 | 124 | /* Testing Code */ 125 | const ar = ['A', 'B', 'C', 'D', 'E']; 126 | const fr = [30, 25, 21, 14, 10]; 127 | const hf = new HuffmanTree(ar, fr); 128 | hf.print(); 129 | 130 | /* 131 | Char = Huffman code 132 | C = 00 133 | E = 010 134 | D = 011 135 | B = 10 136 | A = 11 137 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/JobSequencing.js: -------------------------------------------------------------------------------- 1 | class Job { 2 | constructor(id, deadline, profit) { 3 | this.id = id; 4 | this.deadline = deadline; 5 | this.profit = profit; 6 | } 7 | } 8 | 9 | class JobSequencing { 10 | constructor(ids, deadlines, profits, n) { 11 | this.jobs = Array(n).fill(null); 12 | this.n = n; 13 | this.maxDL = deadlines[0]; 14 | for (let i = 1; i < n; i++) { 15 | if (deadlines[i] > this.maxDL) { 16 | this.maxDL = deadlines[i]; 17 | } 18 | } 19 | for (let i = 0; i < n; i++) { 20 | this.jobs[i] = new Job(ids[i], deadlines[i], profits[i]); 21 | } 22 | } 23 | 24 | print() { 25 | this.jobs.sort(function (a, b){return b.profit - a.profit}); 26 | const result = Array(this.maxDL).fill(false); 27 | const job = Array(this.maxDL).fill(' '); 28 | let profit = 0; 29 | // Iterate through all given jobs 30 | for (let i = 0; i < this.n; i++) { 31 | for (let j = this.jobs[i].deadline - 1; j >= 0; j--) { 32 | if (result[j] == false) { 33 | result[j] = true; 34 | job[j] = this.jobs[i].id; 35 | profit += this.jobs[i].profit; 36 | break; 37 | } 38 | } 39 | } 40 | console.log("Profit is :: " + profit); 41 | 42 | let output = "Jobs selected are::"; 43 | for (let i = 0; i < this.maxDL; i++) { 44 | if (job[i] != '') { 45 | output += " " + job[i]; 46 | } 47 | } 48 | console.log(output); 49 | } 50 | } 51 | 52 | /* Testing Code */ 53 | const id = ['a', 'b', 'c', 'd', 'e']; 54 | const deadline = [3, 1, 2, 4, 4]; 55 | const profit = [50, 40, 27, 31, 30]; 56 | let js = new JobSequencing(id, deadline, profit, 5); 57 | js.print(); 58 | 59 | /* 60 | Profit is :: 151 61 | Jobs selected are:: b e a d 62 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/JoinRopes.js: -------------------------------------------------------------------------------- 1 | greater = (x, y) => (x > y); 2 | less = (x, y) => (x < y); 3 | 4 | class PriorityQueue { 5 | constructor(cmp) { 6 | this.comp = cmp; 7 | this.size = 0; 8 | this.arr = []; 9 | } 10 | 11 | /* Other methods */ 12 | percolateDown(parent) { 13 | const lChild = 2 * parent + 1; 14 | const rChild = lChild + 1; 15 | let child = -1; 16 | let temp; 17 | if (lChild <= this.size) { 18 | child = lChild; 19 | } 20 | if (rChild <= this.size && this.comp(this.arr[lChild], this.arr[rChild])) { 21 | child = rChild; 22 | } 23 | if (child !== -1 && this.comp(this.arr[parent], this.arr[child])) { 24 | temp = this.arr[parent]; 25 | this.arr[parent] = this.arr[child]; 26 | this.arr[child] = temp; 27 | this.percolateDown(child); 28 | } 29 | } 30 | 31 | percolateUp(child) { 32 | const parent = Math.floor((child - 1) / 2); 33 | if (parent < 0) { 34 | return; 35 | } 36 | if (this.comp(this.arr[parent], this.arr[child])) { 37 | const temp = this.arr[child]; 38 | this.arr[child] = this.arr[parent]; 39 | this.arr[parent] = temp; 40 | this.percolateUp(parent); 41 | } 42 | } 43 | 44 | add(value) { 45 | this.arr[this.size] = value; 46 | this.size += 1; 47 | this.percolateUp(this.size - 1); 48 | } 49 | 50 | remove() { 51 | if (this.isEmpty()) { 52 | throw new Error("IllegalStateException"); 53 | } 54 | const value = this.arr[0]; 55 | this.arr[0] = this.arr[this.size - 1]; 56 | this.size--; 57 | this.percolateDown(0); 58 | return value; 59 | } 60 | 61 | print() { 62 | console.log(this.arr); 63 | } 64 | 65 | isEmpty() { 66 | return (this.size === 0); 67 | } 68 | 69 | length() { 70 | return this.size; 71 | } 72 | 73 | peek() { 74 | if (this.isEmpty()) { 75 | throw new Error("IllegalStateException"); 76 | } 77 | return this.arr[0] 78 | } 79 | } 80 | 81 | function joinRopes(ropes, size) { 82 | ropes.sort(function(a, b) { return b - a; }); 83 | let total = 0, value = 0, index = 0, length = size; 84 | while (length >= 2) { 85 | value = ropes[length - 1] + ropes[length - 2]; 86 | total += value; 87 | index = length - 2; 88 | while (index > 0 && ropes[index - 1] < value) { 89 | ropes[index] = ropes[index - 1]; 90 | index -= 1; 91 | } 92 | ropes[index] = value; 93 | length--; 94 | } 95 | console.log("Total : " + total); 96 | return total; 97 | } 98 | 99 | function joinRopes2(ropes, size) { 100 | const pq = new PriorityQueue(function(a, b) { return (a > b)}); 101 | for (let i = 0; i < size; i++) { 102 | pq.add(ropes[i]); 103 | } 104 | let total = 0, value = 0; 105 | while (pq.length() > 1) { 106 | value = pq.remove(); 107 | value += pq.remove(); 108 | pq.add(value); 109 | total += value; 110 | } 111 | console.log("Total : " + total); 112 | return total; 113 | } 114 | 115 | /* Testing Code */ 116 | const ropes = [4, 3, 2, 6]; 117 | joinRopes(ropes, ropes.length); 118 | const rope2 = [4, 3, 2, 6]; 119 | joinRopes2(rope2, rope2.length); 120 | 121 | /* 122 | Total : 29 123 | Total : 29 124 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/Knapsack.js: -------------------------------------------------------------------------------- 1 | 2 | class Items { 3 | constructor(w, v) { 4 | this.wt = w; 5 | this.cost = v; 6 | this.density =v / w; 7 | } 8 | } 9 | 10 | // Approximate solution. 11 | function getMaxCostGreedy(wt, cost, capacity) { 12 | let totalCost = 0; 13 | const n = wt.length; 14 | const itemList = Array(n).fill(null); 15 | for (let i = 0; i < n; i++) 16 | itemList[i] = new Items(wt[i], cost[i]); 17 | 18 | itemList.sort(function (a, b) { return b.density - a.density }); // Decrease Density 19 | for (let i = 0; i < n && capacity > 0; i++) { 20 | if (capacity - itemList[i].wt >= 0) { 21 | capacity -= itemList[i].wt; 22 | totalCost += itemList[i].cost; 23 | } 24 | } 25 | return totalCost; 26 | } 27 | 28 | /* Testing Code */ 29 | const wt = [10, 40, 20, 30]; 30 | const cost = [60, 40, 90, 120]; 31 | const capacity = 50; 32 | let maxCost = getMaxCostGreedy(wt, cost, capacity); 33 | console.log("Maximum cost obtained = " + maxCost); 34 | 35 | /* 36 | Maximum cost obtained = 150 37 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/MultipleStageGraph.js: -------------------------------------------------------------------------------- 1 | 2 | const INF = Number.MAX_VALUE; 3 | 4 | // Returns shortest distance from 0 to N-1. 5 | function shortestDist(graph, n) { 6 | // dist[i] is going to store shortest 7 | // distance from node i to node n-1. 8 | const dist = Array(n).fill(INF); 9 | const path = Array(n).fill(0); 10 | let value = 0; 11 | dist[0] = 0; 12 | path[0] = -1; 13 | 14 | // Calculating shortest path for the nodes 15 | for (let i = 0; i < n; i++) { 16 | // Check all nodes of next 17 | for (let j = i; j < n; j++) { 18 | // Reject if no edge exists 19 | if (graph[i][j] == INF) 20 | continue; 21 | 22 | value = graph[i][j] + dist[i]; 23 | if (dist[j] > value) { 24 | dist[j] = value; 25 | path[j] = i; 26 | } 27 | } 28 | } 29 | value = n-1; 30 | let pathOut = ""; 31 | while (value != -1) { 32 | pathOut = " " + value + pathOut; 33 | value = path[value]; 34 | } 35 | pathOut = "Path is :" + pathOut; 36 | console.log(pathOut); 37 | return dist[n-1]; 38 | } 39 | 40 | /* Testing Code */ 41 | // Graph stored in the form of an adjacency Matrix 42 | const graph = [ 43 | [INF, 1, 2, 5, INF, INF, INF, INF], 44 | [INF, INF, INF, INF, 4, 11, INF, INF], 45 | [INF, INF, INF, INF, 9, 5, 16, INF], 46 | [INF, INF, INF, INF, INF, INF, 2, INF], 47 | [INF, INF, INF, INF, INF, INF, INF, 18], 48 | [INF, INF, INF, INF, INF, INF, INF, 13], 49 | [INF, INF, INF, INF, INF, INF, INF, 2], 50 | [INF, INF, INF, INF, INF, INF, INF, INF] 51 | ]; 52 | console.log(shortestDist(graph, 8)); 53 | 54 | /* 55 | Path is : 0 3 6 7 56 | 9 57 | */ -------------------------------------------------------------------------------- /AlgorithmsChapters/Greedy/OptimalMergePattern.js: -------------------------------------------------------------------------------- 1 | greater = (x, y) => (x > y); 2 | less = (x, y) => (x < y); 3 | 4 | class PriorityQueue { 5 | constructor(cmp) { 6 | this.comp = cmp; 7 | this.size = 0; 8 | this.arr = []; 9 | } 10 | 11 | /* Other methods */ 12 | percolateDown(parent) { 13 | const lChild = 2 * parent + 1; 14 | const rChild = lChild + 1; 15 | let child = -1; 16 | let temp; 17 | if (lChild <= this.size) { 18 | child = lChild; 19 | } 20 | if (rChild <= this.size && this.comp(this.arr[lChild], this.arr[rChild])) { 21 | child = rChild; 22 | } 23 | if (child !== -1 && this.comp(this.arr[parent], this.arr[child])) { 24 | temp = this.arr[parent]; 25 | this.arr[parent] = this.arr[child]; 26 | this.arr[child] = temp; 27 | this.percolateDown(child); 28 | } 29 | } 30 | 31 | percolateUp(child) { 32 | const parent = Math.floor((child-1) / 2); 33 | if (parent < 0) { 34 | return; 35 | } 36 | if (this.comp(this.arr[parent], this.arr[child])) { 37 | const temp = this.arr[child]; 38 | this.arr[child] = this.arr[parent]; 39 | this.arr[parent] = temp; 40 | this.percolateUp(parent); 41 | } 42 | } 43 | 44 | add(value) { 45 | this.arr[this.size] = value; 46 | this.size += 1; 47 | this.percolateUp(this.size-1); 48 | } 49 | 50 | remove() { 51 | if (this.isEmpty()) { 52 | throw new Error("IllegalStateException"); 53 | } 54 | const value = this.arr[0]; 55 | this.arr[0] = this.arr[this.size-1]; 56 | this.size--; 57 | this.percolateDown(0); 58 | return value; 59 | } 60 | 61 | print() { 62 | console.log(this.arr); 63 | } 64 | 65 | isEmpty() { 66 | return (this.size === 0); 67 | } 68 | 69 | length() { 70 | return this.size; 71 | } 72 | 73 | peek() { 74 | if (this.isEmpty()) { 75 | throw new Error("IllegalStateException"); 76 | } 77 | return this.arr[0] 78 | } 79 | } 80 | 81 | function optimalMerge(lists, size) { 82 | const pq = new PriorityQueue(function(a, b) { return (a > b)}); 83 | for (let i = 0; i < size; i++) 84 | pq.add(lists[i]); 85 | 86 | let total = 0; 87 | let value = 0; 88 | while (pq.length() > 1) { 89 | value = pq.remove(); 90 | value += pq.remove(); 91 | pq.add(value); 92 | total += value; 93 | } 94 | console.log("Total : " + total); 95 | return total; 96 | } 97 | 98 | /* Testing Code */ 99 | const lists = [4, 3, 2, 6]; 100 | optimalMerge(lists, lists.length); 101 | 102 | /* 103 | Total : 29 104 | */ -------------------------------------------------------------------------------- /HashTable/CountMap.js: -------------------------------------------------------------------------------- 1 | class CountMap { 2 | constructor() { 3 | this.hm = new Map(); 4 | } 5 | 6 | insert(key) { 7 | if (this.hm.has(key)) { 8 | const cnt = this.hm.get(key); 9 | this.hm.set(key, cnt + 1); 10 | } else { 11 | this.hm.set(key, 1); 12 | } 13 | } 14 | 15 | remove(key) { 16 | if (this.hm.has(key)) { 17 | if (this.hm.get(key) === 1) 18 | this.hm.delete(key); 19 | else { 20 | const cnt = this.hm.get(key); 21 | this.hm.set(key, cnt - 1); 22 | } 23 | } 24 | } 25 | 26 | get(key) { 27 | if (this.hm.has(key)) 28 | return this.hm.get(key); 29 | return 0; 30 | } 31 | 32 | find(key) { 33 | return this.hm.has(key); 34 | } 35 | } 36 | 37 | // Testing code. 38 | const cm = new CountMap(); 39 | cm.insert(2); 40 | cm.insert(2); 41 | cm.remove(2); 42 | console.log(`count is : ${cm.get(2)}`); 43 | cm.remove(2); 44 | console.log(`count is : ${cm.get(2)}`); 45 | console.log(`count is : ${cm.get(3)}`); -------------------------------------------------------------------------------- /HashTable/HashTableExercise.js: -------------------------------------------------------------------------------- 1 | class CountMap { 2 | constructor() { 3 | this.hm = new Map(); 4 | } 5 | 6 | add(key) { 7 | if (this.hm.has(key)) { 8 | const cnt = this.hm.get(key); 9 | this.hm.set(key, cnt + 1); 10 | } else { 11 | this.hm.set(key, 1); 12 | } 13 | } 14 | 15 | remove(key) { 16 | if (this.hm.has(key)) { 17 | if (this.hm.get(key) === 1) 18 | this.hm.delete(key); 19 | else { 20 | const cnt = this.hm.get(key); 21 | this.hm.set(key, cnt - 1); 22 | } 23 | } 24 | } 25 | 26 | get(key) { 27 | if (this.hm.has(key)) 28 | return this.hm.get(key); 29 | return 0; 30 | } 31 | 32 | find(key) { 33 | return this.hm.has(key); 34 | } 35 | 36 | size(key) { 37 | return this.hm.size; 38 | } 39 | } 40 | 41 | /* Testing Code */ 42 | const cm = new CountMap(); 43 | cm.insert(2); 44 | cm.insert(2); 45 | console.log(`count of 2 is : ${cm.get(2)}`); 46 | cm.remove(2); 47 | console.log(`count of 2 is : ${cm.get(2)}`); 48 | cm.remove(2); 49 | console.log(`count of 2 is : ${cm.get(2)}`); 50 | console.log(`count of 3 is : ${cm.get(3)}`); 51 | 52 | function isAnagram(str1, str2){ 53 | const size1 = str1.length; 54 | const size2 = str2.length; 55 | if (size1 !== size2) 56 | return false; 57 | 58 | const cm = new CountMap(); 59 | for (let index = 0; index < str1.length; index++) { 60 | let ch = str1[index]; 61 | cm.add(ch); 62 | } 63 | for (let index = 0; index < str2.length; index++) { 64 | let ch = str2[index]; 65 | cm.remove(ch); 66 | } 67 | return (cm.size() === 0); 68 | } 69 | 70 | // Testing code. 71 | function test1(){ 72 | const first = "hello"; 73 | const second = "elloh"; 74 | const third = "world"; 75 | console.log(`isAnagram : ${isAnagram(first, second)}`); 76 | console.log(`isAnagram : ${isAnagram(first, third)}`); 77 | } 78 | 79 | test1() 80 | /* 81 | isAnagram : true 82 | isAnagram : false 83 | */ 84 | 85 | function removeDuplicate(str){ 86 | let str2 = ""; 87 | const hs = new Set(); 88 | for (let ind = 0; ind < str.length; ind++) { 89 | const ch = str[ind]; 90 | if (hs.has(ch.charCodeAt(0)) === false) { 91 | str2 += ch; 92 | hs.add(ch.charCodeAt(0)); 93 | } 94 | } 95 | return str2; 96 | } 97 | 98 | // Testing code. 99 | function test2(){ 100 | const first = "hello"; 101 | console.log(removeDuplicate(first)); 102 | } 103 | 104 | test2() 105 | /* 106 | helo 107 | */ 108 | 109 | function findMissing(arr, start, end){ 110 | const hs = new Set(); 111 | for (let index = 0; index < arr.length; index++) { 112 | hs.add(arr[index]); 113 | } 114 | for (let curr = start; curr <= end; curr++) { 115 | if (hs.has(curr) === false) 116 | return curr; 117 | } 118 | return -1; 119 | } 120 | 121 | // Testing code. 122 | function test3(){ 123 | const arr = [1, 2, 3, 5, 6, 7, 8, 9, 10]; 124 | console.log("Missing element is :", findMissing(arr, 1, 10)); 125 | } 126 | 127 | test3() 128 | /* 129 | Missing element is : 4 130 | */ 131 | 132 | function printRepeating(arr) { 133 | const hs = new Set(); 134 | console.log("Repeating elements are:"); 135 | for (let insert = 0; insert < arr.length; insert++) { 136 | const val = arr[insert]; 137 | 138 | if (hs.has(val)) 139 | console.log(val); 140 | else 141 | hs.add(val); 142 | } 143 | } 144 | 145 | function printFirstRepeating(arr){ 146 | const size = arr.length; 147 | const hs = new CountMap(); 148 | for (let i = 0; i < size; i++) { 149 | hs.add(arr[i]); 150 | } 151 | for (let i = 0; i < size; i++) { 152 | hs.remove(arr[i]); 153 | if (hs.find(arr[i])) { 154 | console.log(`First Repeating number is : ${arr[i]}`); 155 | return; 156 | } 157 | } 158 | } 159 | 160 | // Testing code. 161 | function test4(){ 162 | const arr1 = [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 1]; 163 | printRepeating(arr1); 164 | printFirstRepeating(arr1); 165 | } 166 | 167 | test4() 168 | /* 169 | Repeating elements are: 170 | 4 171 | 1 172 | First Repeating number is : 1 173 | */ 174 | 175 | function hornerHash(key, tableSize){ 176 | const size = key.length; 177 | let h = 0; 178 | for (let i = 0; i < size; i++) { 179 | h = (32 * h + key[i]) % tableSize; 180 | } 181 | return h; 182 | } -------------------------------------------------------------------------------- /HashTable/HashTableLP.js: -------------------------------------------------------------------------------- 1 | EMPTY_VALUE = -1; 2 | DELETED_VALUE = -2; 3 | FILLED_VALUE = 0; 4 | 5 | class HashTable { 6 | constructor(tSize, cmp, hashFun) { 7 | this.comp = (cmp === undefined || cmp === null) ? this.DefaultCompare : cmp; 8 | this.HashFun = (hashFun === undefined || hashFun === null) ? this.DefaultHashFun : hashFun; 9 | this.tableSize = tSize; 10 | this.KeyArr = new Array(tSize + 1); 11 | this.DataArr = new Array(tSize + 1); 12 | this.FlagArr = new Array(tSize + 1).fill(EMPTY_VALUE); 13 | } 14 | 15 | ComputeHash(key) { 16 | return this.HashFun(key) % this.tableSize; 17 | } 18 | 19 | resolverFun(index) { 20 | return index; 21 | } 22 | 23 | DefaultCompare(first, second) { 24 | return first - second; 25 | } 26 | 27 | DefaultHashFun(key) { 28 | return key; 29 | } 30 | /* Other methods */ 31 | 32 | add(key, value) { 33 | if (key === undefined || key === null) 34 | return false; 35 | 36 | if (value === undefined || value === null) 37 | value = key; 38 | 39 | let hashValue = this.ComputeHash(key); 40 | for (let i = 0; i < this.tableSize; i++) { 41 | if ((this.FlagArr[hashValue] === EMPTY_VALUE) || 42 | (this.FlagArr[hashValue] === DELETED_VALUE)) { 43 | this.DataArr[hashValue] = value; 44 | this.KeyArr[hashValue] = key; 45 | this.FlagArr[hashValue] = FILLED_VALUE; 46 | return true; 47 | } else if (this.FlagArr[hashValue] === FILLED_VALUE && 48 | this.KeyArr[hashValue] === key) { 49 | this.DataArr[hashValue] = value; 50 | return true; 51 | } 52 | 53 | hashValue += this.resolverFun(i); 54 | hashValue %= this.tableSize; 55 | } 56 | return false; 57 | } 58 | 59 | find(key) { 60 | if (key === undefined || key === null) 61 | return false; 62 | 63 | let hashValue = this.ComputeHash(key); 64 | for (let i = 0; i < this.tableSize; i++) { 65 | if (this.FlagArr[hashValue] === EMPTY_VALUE) { 66 | return false; 67 | } 68 | if (this.FlagArr[hashValue] === FILLED_VALUE 69 | && this.KeyArr[hashValue] === key) { 70 | return true; 71 | } 72 | hashValue += this.resolverFun(i); 73 | hashValue %= this.tableSize; 74 | } 75 | return false; 76 | } 77 | 78 | get(key) { 79 | if (key === undefined || key === null) 80 | return false; 81 | 82 | let hashValue = this.ComputeHash(key); 83 | for (let i = 0; i < this.tableSize; i++) { 84 | if (this.FlagArr[hashValue] === EMPTY_VALUE) { 85 | return 0; 86 | } 87 | if (this.FlagArr[hashValue] === FILLED_VALUE 88 | && this.KeyArr[hashValue] === key) { 89 | return this.DataArr[hashValue]; 90 | } 91 | hashValue += this.resolverFun(i); 92 | hashValue %= this.tableSize; 93 | } 94 | return 0; 95 | } 96 | 97 | remove(key) { 98 | if (key === undefined || key === null) 99 | return false; 100 | 101 | let hashValue = this.ComputeHash(key); 102 | for (let i = 0; i < this.tableSize; i++) { 103 | if (this.FlagArr[hashValue] === EMPTY_VALUE) { 104 | return false; 105 | } 106 | if (this.FlagArr[hashValue] === FILLED_VALUE 107 | && this.KeyArr[hashValue] === key) { 108 | this.FlagArr[hashValue] = DELETED_VALUE; 109 | return true; 110 | } 111 | hashValue += this.resolverFun(i); 112 | hashValue %= this.tableSize; 113 | } 114 | return false; 115 | } 116 | 117 | print() { 118 | let output = "Hash Table contains ::"; 119 | for (let i = 0; i < this.tableSize; i++) { 120 | if (this.FlagArr[i] === FILLED_VALUE) { 121 | output += "(" + this.KeyArr[i] + "=>" + this.DataArr[i] + ") "; 122 | } 123 | } 124 | console.log(output); 125 | } 126 | } 127 | 128 | // Testing code. 129 | const ht = new HashTable(1000); 130 | ht.add(1, 10); 131 | ht.add(2, 20); 132 | ht.add(3, 30); 133 | ht.print(); 134 | 135 | console.log("Find key 2 : ", ht.find(2)); 136 | console.log("Value at key 2 : ",ht.get(2)) 137 | ht.remove(1) 138 | ht.print() 139 | 140 | /* 141 | Hash Table contains ::(1=>10) (2=>20) (3=>30) 142 | Find key 2 : true 143 | Value at key 2 : 20 144 | Hash Table contains ::(2=>20) (3=>30) 145 | */ -------------------------------------------------------------------------------- /HashTable/HashTableSC.js: -------------------------------------------------------------------------------- 1 | class HashTableNode { 2 | constructor(k, v, n) { 3 | this.key = k; 4 | this.value = v; 5 | this.next = n; 6 | } 7 | } 8 | 9 | class HashTable { 10 | constructor(cmp, hashFun) { 11 | this.comp = (cmp === undefined || cmp === null) ? this.DefaultCompare : cmp; 12 | this.HashFun = (hashFun === undefined || hashFun === null) ? this.DefaultHashFun : hashFun; 13 | this.tableSize = 512; 14 | this.listArray = new Array(this.tableSize).fill(null); 15 | } 16 | 17 | ComputeHash(key) { 18 | return this.HashFun(key) % this.tableSize; 19 | } 20 | 21 | DefaultCompare(first, second) { 22 | return first - second; 23 | } 24 | 25 | DefaultHashFun(key) { 26 | return key; 27 | } 28 | /* Other methods */ 29 | 30 | add(key, value) { 31 | if (key === undefined || key === null) 32 | return false; 33 | 34 | if (value === undefined || value === null) 35 | value = key; 36 | 37 | const index = this.ComputeHash(key); 38 | this.listArray[index] = new HashTableNode(key, value,this.listArray[index]); 39 | } 40 | 41 | remove(key) { 42 | const index = this.ComputeHash(key); 43 | let nextNode; 44 | let head = this.listArray[index]; 45 | if (head != null && head.key === key) { 46 | this.listArray[index] = head.next; 47 | return true; 48 | } 49 | 50 | while (head != null) { 51 | nextNode = head.next; 52 | if (nextNode != null && nextNode.key === key) { 53 | head.next = nextNode.next; 54 | return true; 55 | } else { 56 | head = nextNode; 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | print() { 63 | let output = "Hash Table contains ::"; 64 | for (let i = 0; i < this.tableSize; i++) { 65 | let head = this.listArray[i]; 66 | while (head != null) { 67 | output += "(" + head.key + "=>" +head.value + ") " 68 | head = head.next; 69 | } 70 | } 71 | console.log(output); 72 | } 73 | 74 | find(key) { 75 | const index = this.ComputeHash(key); 76 | let head = this.listArray[index]; 77 | while (head != null) { 78 | if (head.key === key) { 79 | return true; 80 | } 81 | head = head.next; 82 | } 83 | return false; 84 | } 85 | 86 | get(key) { 87 | const index = this.ComputeHash(key); 88 | let head = this.listArray[index]; 89 | while (head != null) { 90 | if (head.key === key) { 91 | return head.value; 92 | } 93 | head = head.next; 94 | } 95 | return 0; 96 | } 97 | } 98 | 99 | 100 | // Testing code. 101 | const ht = new HashTable(); 102 | ht.add(1, 10); 103 | ht.add(2, 20); 104 | ht.add(3, 30); 105 | ht.print(); 106 | 107 | console.log("Find key 2 : ", ht.find(2)); 108 | console.log("Value at key 2 : ",ht.get(2)) 109 | ht.remove(1) 110 | ht.print() -------------------------------------------------------------------------------- /Introduction/Analysis.js: -------------------------------------------------------------------------------- 1 | function fun1(n) { 2 | let m = 0; 3 | for (let i = 0; i < n; i++) { 4 | m += 1; 5 | } 6 | return m; 7 | } 8 | 9 | console.log(`Number of instructions O(n):: ${fun1(100)}`); 10 | 11 | //Output: Number of instructions O(n):: 100 12 | 13 | function fun2(n) { 14 | let m = 0; 15 | for (let i = 0; i < n; i++) { 16 | for (let j = 0; j < n; j++) { 17 | m += 1; 18 | } 19 | } 20 | return m; 21 | } 22 | 23 | console.log(`Number of instructions O(n^2):: ${fun2(100)}`); 24 | 25 | //Output: Number of instructions O(n^2):: 10000 26 | 27 | 28 | function fun3(n) { 29 | let m = 0; 30 | for (let i = 0; i < n; i++) { 31 | for (let j = 0; j < n; j++) { 32 | for (let k = 0; k < n; k++) { 33 | m += 1; 34 | } 35 | } 36 | } 37 | return m; 38 | } 39 | 40 | console.log(`Number of instructions O(n^3):: ${fun3(100)}`); 41 | 42 | //Output: Number of instructions O(n^3):: 1000000 43 | 44 | function fun4(n) { 45 | let m = 0; 46 | for (let i = 0; i < n; i++) { 47 | for (let j = i; j < n; j++) { 48 | for (let k = j + 1; k < n; k++) { 49 | m += 1; 50 | } 51 | } 52 | } 53 | return m; 54 | } 55 | 56 | console.log(`Number of instructions O(n^3):: ${fun4(100)}`); 57 | 58 | //Output: Number of instructions O(n^3):: 166650 59 | 60 | function fun5(n) { 61 | let m = 0; 62 | for (let i = 0; i < n; i++) { 63 | for (let j = 0; j < i; j++) { 64 | m += 1; 65 | } 66 | } 67 | return m; 68 | } 69 | 70 | console.log(`Number of instructions O(n^2):: ${fun5(100)}`); 71 | 72 | //Output: Number of instructions O(n^2):: 4950 73 | 74 | function fun6(n) { 75 | let m = 0; 76 | for (let i = 0; i < n; i++) { 77 | for (let j = i; j > 0; j--) { 78 | m += 1; 79 | } 80 | } 81 | return m; 82 | } 83 | 84 | console.log(`Number of instructions O(n^2):: ${fun6(100)}`); 85 | 86 | //Output: Number of instructions O(n^2):: 4950 87 | 88 | function fun7(n) { 89 | let m = 0; 90 | for (let i = n; i > 1; i /= 2) { 91 | for (let j = 0; j < i; j++) { 92 | m += 1; 93 | } 94 | } 95 | return m; 96 | } 97 | 98 | console.log(`Number of instructions O(n):: ${fun7(100)}`); 99 | 100 | //Output: Number of instructions O(n):: 201 101 | 102 | function fun8(n) { 103 | let m = 0; 104 | for (let i = 1; i <= n; i *= 2) { 105 | for (let j = 0; j <= i; j++) { 106 | m += 1; 107 | } 108 | } 109 | return m; 110 | } 111 | 112 | console.log(`Number of instructions O(n):: ${fun8(100)}`); 113 | 114 | //Output: Number of instructions O(n):: 134 115 | 116 | 117 | function fun9(n) { 118 | let i = 1; 119 | let m = 0; 120 | while (i < n) { 121 | m += 1; 122 | i = i * 2; 123 | } 124 | return m; 125 | } 126 | 127 | console.log(`Number of instructions O(log(n)):: ${fun9(100)}`); 128 | 129 | //Output: Number of instructions O(log(n)):: 7 130 | 131 | function fun10(n) { 132 | let i = n; 133 | let m = 0; 134 | while (i > 0) { 135 | m += 1; 136 | i = Math.floor(i / 2); 137 | } 138 | return m; 139 | } 140 | 141 | console.log(`Number of instructions O(log(n)):: ${fun10(100)}`); 142 | 143 | //Output: Number of instructions O(log(n)):: 7 144 | 145 | 146 | function fun11(n) { 147 | let i, j, k; 148 | let m = 0; 149 | for (i = 0; i < n; i++) { 150 | for (j = 0; j < n; j++) { 151 | m += 1; 152 | } 153 | } 154 | for (i = 0; i < n; i++) { 155 | for (k = 0; k < n; k++) { 156 | m += 1; 157 | } 158 | } 159 | return m; 160 | } 161 | 162 | console.log(`Number of instructions O(n^2):: ${fun11(100)}`); 163 | 164 | //Output: Number of instructions O(n^2):: 20000 165 | 166 | function fun12(n) { 167 | let m = 0; 168 | for (let i = 0; i < n; i++) { 169 | for (let j = 0; j < Math.sqrt(n); j++) { 170 | m += 1; 171 | } 172 | } 173 | return m; 174 | } 175 | 176 | console.log(`Number of instructions O(n^(3/2)):: ${fun12(100)}`); 177 | 178 | //Output: Number of instructions O(n^(3/2)):: 1000 179 | 180 | function fun13(n) { 181 | let j = 0; 182 | let m = 0; 183 | for (let i = 0; i < n; i++) { 184 | for (; j < n; j++) { 185 | m += 1; 186 | } 187 | } 188 | return m; 189 | } 190 | 191 | console.log(`Number of instructions O(n):: ${fun13(100)}`); 192 | 193 | //Output: Number of instructions O(n):: 100 194 | -------------------------------------------------------------------------------- /Introduction/Introduction.js: -------------------------------------------------------------------------------- 1 | function factorial(i) { 2 | if (i <= 1) { 3 | return 1; 4 | } 5 | return i * factorial(i - 1); 6 | } 7 | 8 | // Testing code. 9 | console.log("factorial 5 is ::", factorial(5)) 10 | 11 | /* 12 | factorial 5 is :: 120 13 | */ 14 | 15 | function printIntUtil(number, base, arr) { 16 | const conversion = "0123456789ABCDEF"; 17 | const digit = (number % base); 18 | number = Math.floor(number / base); 19 | if (number !== 0) { 20 | printIntUtil(number, base, arr); 21 | } 22 | arr.push(conversion[digit]); 23 | } 24 | 25 | function printInt(number, base) { 26 | const arr = new Array(); 27 | printIntUtil(number, base, arr); 28 | return arr.join(""); 29 | } 30 | 31 | // Testing code. 32 | console.log(printInt(500, 16)); 33 | /* 34 | 1F4 35 | */ 36 | function towerOfHanoi(num, src, dst, temp) { 37 | if (num < 1) { 38 | return; 39 | } 40 | towerOfHanoi(num - 1, src, temp, dst); 41 | console.log(`Move ${num} disk from peg ${src} to peg ${dst}`); 42 | towerOfHanoi(num - 1, temp, dst, src); 43 | } 44 | 45 | // Testing code. 46 | const num = 3; 47 | console.log("The sequence of moves are :"); 48 | towerOfHanoi(num, 'A', 'C', 'B'); 49 | 50 | /* 51 | The sequence of moves are : 52 | Move 1 disk from peg A to peg C 53 | Move 2 disk from peg A to peg B 54 | Move 1 disk from peg C to peg B 55 | Move 3 disk from peg A to peg C 56 | Move 1 disk from peg B to peg A 57 | Move 2 disk from peg B to peg C 58 | Move 1 disk from peg A to peg C 59 | */ 60 | 61 | 62 | function gcd(m, n) { 63 | if (n == 0) 64 | return m; 65 | 66 | if (m == 0) 67 | return n; 68 | 69 | return (gcd(n, m % n)); 70 | } 71 | 72 | // Testing code. 73 | console.log(gcd(15, 7)); 74 | /* 75 | 1 76 | */ 77 | function fibonacci(n) { 78 | if (n < 2) { 79 | return n; 80 | } 81 | return fibonacci(n - 1) + fibonacci(n - 2); 82 | } 83 | 84 | function fibonacci2(n) { 85 | let first = 0; 86 | let second = 1; 87 | let temp; 88 | 89 | if (n === 0) 90 | return first; 91 | else if (n === 1) 92 | return second; 93 | 94 | for (let i = 2; i <= n; i++) { 95 | temp = first + second; 96 | first = second; 97 | second = temp; 98 | } 99 | return temp; 100 | } 101 | 102 | // Testing code. 103 | console.log(fibonacci(10)); 104 | console.log(fibonacci2(10)); 105 | 106 | /* 107 | 55 108 | 55 109 | */ 110 | 111 | -------------------------------------------------------------------------------- /Language and Collections/ArrayDemo.js: -------------------------------------------------------------------------------- 1 | const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 2 | console.log(JSON.stringify(arr)); 3 | 4 | const arr2 = new Array(10).fill(0); 5 | for (let i = 0; i < 10; i++) 6 | arr2[i] = i; 7 | 8 | console.log(JSON.stringify(arr2)); 9 | 10 | /* 11 | [1,2,3,4,5,6,7,8,9,10] 12 | [0,1,2,3,4,5,6,7,8,9] 13 | */ -------------------------------------------------------------------------------- /Language and Collections/CounterMap.js: -------------------------------------------------------------------------------- 1 | class CountMap { 2 | constructor() { 3 | this.hm = new Map(); 4 | } 5 | 6 | insert(key) { 7 | if (this.hm.has(key)) { 8 | const cnt = this.hm.get(key); 9 | this.hm.set(key, cnt + 1); 10 | } else { 11 | this.hm.set(key, 1); 12 | } 13 | } 14 | 15 | remove(key) { 16 | if (this.hm.has(key)) { 17 | if (this.hm.get(key) === 1) 18 | this.hm.delete(key); 19 | else { 20 | const cnt = this.hm.get(key); 21 | this.hm.set(key, cnt - 1); 22 | } 23 | } 24 | } 25 | 26 | get(key) { 27 | if (this.hm.has(key)) 28 | return this.hm.get(key); 29 | return 0; 30 | } 31 | 32 | find(key) { 33 | return this.hm.has(key); 34 | } 35 | } 36 | 37 | const cm = new CountMap(); 38 | cm.insert(2); 39 | cm.insert(2); 40 | cm.remove(2); 41 | console.log(`count of 2 is : ${cm.get(2)}`); 42 | cm.remove(2); 43 | console.log(`count of 2 is : ${cm.get(2)}`); 44 | console.log(`count of 3 is : ${cm.get(3)}`); -------------------------------------------------------------------------------- /Language and Collections/LoopDemo.js: -------------------------------------------------------------------------------- 1 | function main1() { 2 | const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 3 | let sum = 0; 4 | for (let i = 0; i < numbers.length; i++) { 5 | sum += numbers[i]; 6 | } 7 | console.log(`Sum is :: ${sum}`); 8 | } 9 | 10 | function main2() { 11 | const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 12 | let sum = 0; 13 | let i = 0; 14 | while (i < numbers.length) { 15 | sum += numbers[i]; 16 | i++; 17 | } 18 | console.log(`Sum is :: ${sum}`); 19 | } 20 | 21 | main1(); 22 | main2(); -------------------------------------------------------------------------------- /Language and Collections/MapDemo.js: -------------------------------------------------------------------------------- 1 | const hm = new Map(); 2 | hm.set("Apple", 10) 3 | hm.set("Banana", 20) 4 | hm.set("Mango", 30) 5 | console.log(hm) 6 | console.log(`Map size : ${hm.size}`); 7 | console.log(hm.has("Apple")) 8 | console.log(hm.get("Apple")) 9 | console.log(hm.has("Grape")) 10 | 11 | 12 | const hm2 = {}; 13 | hm2["Apple"] = 10 14 | hm2["Banana"] = 20 15 | hm2["Mango"] = 30 16 | console.log(hm2) 17 | console.log(`Map size : ${Object.keys(hm2).length}`); 18 | console.log(hm2.hasOwnProperty("Apple")) 19 | console.log(hm2["Apple"]) 20 | console.log(hm2.hasOwnProperty("Grape")) 21 | 22 | 23 | /* 24 | Map(3) { 'Apple' => 10, 'Banana' => 20, 'Mango' => 30 } 25 | Map size : 3 26 | true 27 | 10 28 | false 29 | */ 30 | 31 | /* 32 | { Apple: 10, Banana: 20, Mango: 30 } 33 | Map size : 3 34 | true 35 | 10 36 | false 37 | */ 38 | -------------------------------------------------------------------------------- /Language and Collections/MinMaxValueTest.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | const maxByte = 127; 3 | const minByte = -128; 4 | const maxShort = 32767; 5 | const minShort = -32768; 6 | const maxInteger = 2147483647; 7 | const minInteger = -2147483648; 8 | const maxLong = 9223372036854775807; 9 | const minLong = -9223372036854775808; 10 | const maxFloat = 3.4028235E38; 11 | const minFloat = 1.4E-45; 12 | const maxDouble = 1.7976931348623157E308; 13 | const minDouble = 4.9E-324; 14 | console.log(`Range of byte :: ${minByte} to ${maxByte}.`); 15 | console.log(`Range of short :: ${minShort} to ${maxShort}.`); 16 | console.log(`Range of integer :: ${minInteger} to ${maxInteger}.`); 17 | console.log(`Range of long :: ${minLong} to ${maxLong}.`); 18 | console.log(`Range of float :: ${minFloat} to ${maxFloat}.`); 19 | console.log(`Range of double :: ${minDouble} to ${maxDouble}.`); 20 | } 21 | 22 | main(); 23 | -------------------------------------------------------------------------------- /Language and Collections/QueueDemo copy.js: -------------------------------------------------------------------------------- 1 | const que = []; 2 | que.push(1); 3 | que.push(2); 4 | que.push(3); 5 | console.log(`Queue : ${que}`); 6 | console.log(`Queue isEmpty : ${que.length == 0}`); 7 | console.log(`Queue size : ${que.length}`); 8 | console.log(`Queue front : ${que[0]}`); 9 | console.log(`Queue remove : ${que.shift()}`); 10 | 11 | /* 12 | Queue : 1,2,3 13 | Queue isEmpty : false 14 | Queue size : 3 15 | Queue front : 1 16 | Queue remove : 1 17 | */ -------------------------------------------------------------------------------- /Language and Collections/QueueDemo.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.arr = []; 4 | } 5 | 6 | add(value) { 7 | this.arr.push(value); 8 | } 9 | 10 | remove() { 11 | return this.arr.shift(); 12 | } 13 | 14 | front() { 15 | return this.arr[0]; 16 | } 17 | 18 | isEmpty() { 19 | return this.arr.length === 0 20 | } 21 | 22 | length() { 23 | return this.arr.length 24 | } 25 | } 26 | 27 | const que = new Queue(); 28 | que.add(1); 29 | que.add(2); 30 | que.add(3); 31 | console.log(que); 32 | console.log(`Queue size : ${que.length()}`); 33 | console.log(`Queue isEmpty : ${que.isEmpty()}`); 34 | console.log(`Queue front : ${que.front()}`); 35 | console.log(`Queue remove : ${que.remove()}`); 36 | console.log(`Queue size : ${que.length()}`); 37 | 38 | 39 | /* 40 | Queue { arr: [ 1, 2, 3 ] } 41 | Queue size : 3 42 | Queue isEmpty : false 43 | Queue front : 1 44 | Queue remove : 1 45 | Queue size : 2 46 | 47 | */ -------------------------------------------------------------------------------- /Language and Collections/SetDemo.js: -------------------------------------------------------------------------------- 1 | const hs = new Set(); 2 | hs.add("Banana") 3 | hs.add("Apple") 4 | hs.add("Mango") 5 | console.log(hs); 6 | console.log(`Set size : ${hs.size}`); 7 | console.log(`Apple present : ${hs.has("Apple")}`); 8 | console.log(`Grapes present : ${hs.has("Grapes")}`); 9 | hs.delete("Apple") 10 | console.log(hs); 11 | console.log(`Apple present : ${hs.has("Apple")}`); 12 | 13 | /* 14 | Set(3) { 'Banana', 'Apple', 'Mango' } 15 | Apple present : true 16 | Grapes present : false 17 | Set(2) { 'Banana', 'Mango' } 18 | Apple present : false 19 | */ -------------------------------------------------------------------------------- /Language and Collections/StackDemo.js: -------------------------------------------------------------------------------- 1 | 2 | const stack = []; 3 | stack.push(1); 4 | stack.push(2); 5 | stack.push(3); 6 | 7 | console.log(`Stack : ${stack}`); 8 | console.log(`Stack size : ${stack.length}`); 9 | console.log(`Stack isEmpty : ${stack.length == 0}`); 10 | console.log(`Stack top : ${stack[stack.length - 1]}`); 11 | console.log(`Stack pop : ${stack.pop()}`); 12 | 13 | 14 | 15 | /* 16 | Stack : 1,2,3 17 | Stack size : 3 18 | Stack isEmpty : false 19 | Stack top : 3 20 | Stack pop : 3 21 | */ -------------------------------------------------------------------------------- /Language and Collections/Tree.js: -------------------------------------------------------------------------------- 1 | 2 | function Tree() { 3 | this.root = null; 4 | 5 | function Node(data, left = null, right = null) { 6 | this.value = data; 7 | this.left = left; 8 | this.right = right; 9 | } 10 | Tree.Node = Node 11 | } 12 | 13 | Tree.prototype.insertNode = function(value) { 14 | if (typeof value === 'number') 15 | this.root = this.insertNodeUtil(value, this.root); 16 | else 17 | throw new Error('invalid input arguments'); 18 | } 19 | 20 | Tree.prototype.insertNodeUtil = function(value, node) { 21 | if (node == null) { 22 | node = new Tree.Node(value, null, null); 23 | } 24 | else { 25 | if (node.value > value) { 26 | node.left = this.insertNodeUtil(value, node.left); 27 | } 28 | else { 29 | node.right = this.insertNodeUtil(value, node.right); 30 | } 31 | } 32 | return node; 33 | } 34 | 35 | Tree.prototype.printPreOrder = function() { 36 | this.printPreOrderUtil(this.root); 37 | } 38 | 39 | Tree.prototype.printPreOrderUtil = function(node) { 40 | if (node != null) { 41 | console.log(node.value); 42 | this.printPreOrderUtil(node.left); 43 | this.printPreOrderUtil(node.right); 44 | } 45 | } 46 | 47 | let t = new Tree(); 48 | t.insertNode(5) 49 | t.insertNode(3) 50 | t.insertNode(1) 51 | t.insertNode(4) 52 | t.insertNode(7) 53 | t.insertNode(6) 54 | t.insertNode(8) 55 | t.printPreOrder() 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /LinkedList/CircularLinkedList.js: -------------------------------------------------------------------------------- 1 | class CLNode { 2 | constructor(v, n) { 3 | this.value = v; 4 | this.next = n; 5 | } 6 | } 7 | 8 | class CircularLinkedList { 9 | constructor() { 10 | this.length = 0; 11 | this.tail = null; 12 | } 13 | 14 | size() { 15 | return this.length; 16 | } 17 | 18 | isEmpty() { 19 | return this.length === 0; 20 | } 21 | 22 | peek() { 23 | if (this.isEmpty()) 24 | throw new Error("EmptyListException"); 25 | return this.tail.next.value; 26 | } 27 | 28 | addTail(value) { 29 | const temp = new CLNode(value, null); 30 | if (this.isEmpty()) { 31 | this.tail = temp; 32 | temp.next = temp; 33 | } else { 34 | temp.next = this.tail.next; 35 | this.tail.next = temp; 36 | this.tail = temp; 37 | } 38 | this.length++; 39 | } 40 | 41 | addHead(value) { 42 | const temp = new CLNode(value, null); 43 | if (this.isEmpty()) { 44 | this.tail = temp; 45 | temp.next = temp; 46 | } else { 47 | temp.next = this.tail.next; 48 | this.tail.next = temp; 49 | } 50 | this.length++; 51 | } 52 | 53 | removeHead() { 54 | if (this.isEmpty()) { 55 | throw new Error("EmptyListException"); 56 | } 57 | 58 | const value = this.tail.next.value; 59 | if (this.tail === this.tail.next) 60 | this.tail = null; 61 | else 62 | this.tail.next = this.tail.next.next; 63 | this.length--; 64 | return value; 65 | } 66 | 67 | removeNode(key) { 68 | if (this.isEmpty()) { 69 | return false; 70 | } 71 | 72 | let prev = this.tail; 73 | let curr = this.tail.next; 74 | const head = this.tail.next; 75 | if (curr.value === key) { 76 | if (curr === curr.next) 77 | this.tail = null; 78 | else 79 | this.tail.next = this.tail.next.next; 80 | return true; 81 | } 82 | prev = curr; 83 | curr = curr.next; 84 | while (curr !== head) { 85 | if (curr.value === key) { 86 | if (curr === this.tail) 87 | this.tail = prev; 88 | prev.next = curr.next; 89 | return true; 90 | } 91 | prev = curr; 92 | curr = curr.next; 93 | } 94 | return false; 95 | } 96 | 97 | copyListReversed() { 98 | const cl = new CircularLinkedList(); 99 | let curr = this.tail.next; 100 | const head = curr; 101 | 102 | if (curr != null) { 103 | cl.addHead(curr.value); 104 | curr = curr.next; 105 | } 106 | 107 | while (curr !== head) { 108 | cl.addHead(curr.value); 109 | curr = curr.next; 110 | } 111 | return cl; 112 | } 113 | 114 | copyList() { 115 | const cl = new CircularLinkedList(); 116 | let curr = this.tail.next; 117 | const head = curr; 118 | 119 | if (curr != null) { 120 | cl.addTail(curr.value); 121 | curr = curr.next; 122 | } 123 | 124 | while (curr !== head) { 125 | cl.addTail(curr.value); 126 | curr = curr.next; 127 | } 128 | return cl; 129 | } 130 | 131 | 132 | freeList() { 133 | this.tail = null; 134 | this.length = 0; 135 | } 136 | 137 | print() { 138 | if (this.isEmpty()) { 139 | return; 140 | } 141 | 142 | let temp = this.tail.next; 143 | while (temp !== this.tail) { 144 | process.stdout.write(`${temp.value} `); 145 | temp = temp.next; 146 | } 147 | process.stdout.write(`${temp.value}\n`); 148 | } 149 | 150 | find(data) { 151 | let temp = this.tail; 152 | const size = this.size(); 153 | for (let i = 0; i < size; i++) { 154 | if (temp.value === data) 155 | return true; 156 | temp = temp.next; 157 | } 158 | return false; 159 | } 160 | } 161 | 162 | function main1() { 163 | let ll = new CircularLinkedList(); 164 | ll.addHead(1); 165 | ll.addHead(2); 166 | ll.addHead(3); 167 | ll.print(); 168 | console.log(ll.size()); 169 | console.log(ll.isEmpty()); 170 | console.log(ll.peek()); 171 | console.log(ll.find(3)); 172 | } 173 | 174 | /* 175 | 3 2 1 176 | 3 177 | false 178 | 3 179 | true 180 | */ 181 | 182 | function main2() { 183 | let ll = new CircularLinkedList(); 184 | ll.addTail(1); 185 | ll.addTail(2); 186 | ll.addTail(3); 187 | ll.print(); 188 | } 189 | 190 | /* 191 | 1 2 3 192 | */ 193 | 194 | function main3() { 195 | let ll = new CircularLinkedList(); 196 | ll.addHead(1); 197 | ll.addHead(2); 198 | ll.addHead(3); 199 | ll.print(); 200 | ll.removeHead(); 201 | ll.print(); 202 | ll.removeNode(2); 203 | ll.print(); 204 | ll.freeList(); 205 | ll.print(); 206 | } 207 | 208 | /* 209 | 3 2 1 210 | 2 1 211 | 1 212 | Empty List. 213 | */ 214 | 215 | function main4() { 216 | let ll = new CircularLinkedList(); 217 | ll.addHead(1); 218 | ll.addHead(2); 219 | ll.addHead(3); 220 | ll.print(); 221 | let ll2 = ll.copyList(); 222 | ll2.print(); 223 | let ll3 = ll.copyListReversed(); 224 | ll3.print(); 225 | } 226 | 227 | /* 228 | 3 2 1 229 | 3 2 1 230 | 1 2 3 231 | */ 232 | 233 | function main5() { 234 | let ll = new CircularLinkedList(); 235 | ll.addHead(1); 236 | ll.addHead(2); 237 | ll.addHead(3); 238 | ll.print(); 239 | ll.removeNode(2); 240 | ll.print(); 241 | } 242 | 243 | /* 244 | 3 2 1 245 | 3 1 246 | */ 247 | 248 | main1(); 249 | main2(); 250 | main3(); 251 | main4(); 252 | main5(); 253 | -------------------------------------------------------------------------------- /LinkedList/DoublyCircularLinkedList.js: -------------------------------------------------------------------------------- 1 | class DCLLNode { 2 | constructor(v, nxt, prv) { 3 | this.value = v; 4 | this.next = nxt; 5 | this.prev = prv; 6 | } 7 | } 8 | 9 | class DoublyCircularLinkedList { 10 | constructor() { 11 | this.head = null; 12 | this.tail = null; 13 | this.length = 0; 14 | } 15 | 16 | 17 | size() { 18 | return this.length; 19 | } 20 | 21 | isEmpty() { 22 | return this.length === 0; 23 | } 24 | 25 | peekHead() { 26 | if (this.isEmpty()) 27 | throw new Error("EmptyListError"); 28 | return this.head.value; 29 | } 30 | /* Other methods */ 31 | 32 | addHead(value) { 33 | const newNode = new DCLLNode(value, null, null); 34 | if (this.length === 0) { 35 | this.tail = this.head = newNode; 36 | newNode.next = newNode; 37 | newNode.prev = newNode; 38 | } else { 39 | newNode.next = this.head; 40 | newNode.prev = this.head.prev; 41 | this.head.prev = newNode; 42 | newNode.prev.next = newNode; 43 | this.head = newNode; 44 | } 45 | this.length++; 46 | } 47 | 48 | addTail(value) { 49 | const newNode = new DCLLNode(value, null, null); 50 | if (this.length === 0) { 51 | this.head = this.tail = newNode; 52 | newNode.next = newNode; 53 | newNode.prev = newNode; 54 | } else { 55 | newNode.next = this.tail.next; 56 | newNode.prev = this.tail; 57 | this.tail.next = newNode; 58 | newNode.next.prev = newNode; 59 | this.tail = newNode; 60 | } 61 | this.length++; 62 | } 63 | 64 | removeHead() { 65 | if (this.length === 0) 66 | throw new Error("EmptyListError"); 67 | const value = this.head.value; 68 | this.length--; 69 | if (this.length === 0) { 70 | this.head = null; 71 | this.tail = null; 72 | return value; 73 | } 74 | const next = this.head.next; 75 | next.prev = this.tail; 76 | this.tail.next = next; 77 | this.head = next; 78 | return value; 79 | } 80 | 81 | removeTail() { 82 | if (this.length === 0) 83 | throw new Error("EmptyListError"); 84 | const value = this.tail.value; 85 | this.length--; 86 | if (this.length === 0) { 87 | this.head = null; 88 | this.tail = null; 89 | return value; 90 | } 91 | const prev = this.tail.prev; 92 | prev.next = this.head; 93 | this.head.prev = prev; 94 | this.tail = prev; 95 | return value; 96 | } 97 | 98 | find(key) { 99 | let temp = this.head; 100 | if (this.head == null) 101 | return false; 102 | do { 103 | if (temp.value === key) 104 | return true; 105 | temp = temp.next; 106 | } while (temp !== this.head); 107 | return false; 108 | } 109 | 110 | freeList() { 111 | this.head = null; 112 | this.tail = null; 113 | this.length = 0; 114 | } 115 | 116 | print() { 117 | if (this.isEmpty()) { 118 | return; 119 | } 120 | let temp = this.head; 121 | while (temp !== this.tail) { 122 | process.stdout.write(`${temp.value} `); 123 | temp = temp.next; 124 | } 125 | process.stdout.write(`${temp.value}\n`); 126 | } 127 | } 128 | 129 | function main1() { 130 | let ll = new DoublyCircularLinkedList(); 131 | ll.addHead(1); 132 | ll.addHead(2); 133 | ll.addHead(3); 134 | ll.print(); 135 | console.log("Size : " + ll.size()); 136 | console.log("Is empty : " + ll.isEmpty()); 137 | console.log("Peek : " + ll.peekHead()); 138 | console.log("search : " + ll.find(3)); 139 | } 140 | 141 | /* 142 | 3 2 1 143 | 3 144 | false 145 | 3 146 | true 147 | */ 148 | 149 | function main2() { 150 | let ll = new DoublyCircularLinkedList(); 151 | ll.addTail(1); 152 | ll.addTail(2); 153 | ll.addTail(3); 154 | ll.print(); 155 | 156 | ll.removeHead(); 157 | ll.print(); 158 | ll.removeTail(); 159 | ll.print(); 160 | ll.freeList(); 161 | ll.print(); 162 | } 163 | 164 | /* 165 | 1 2 3 166 | 2 3 167 | 2 168 | Empty List. 169 | */ 170 | 171 | function main3() { 172 | let ll = new DoublyCircularLinkedList(); 173 | ll.addHead(1); 174 | ll.addHead(2); 175 | ll.addHead(3); 176 | ll.print(); 177 | ll.removeHead(); 178 | ll.print(); 179 | 180 | } 181 | 182 | /* 183 | 3 2 1 184 | 2 1 185 | */ 186 | 187 | function main4() { 188 | let ll = new DoublyCircularLinkedList(); 189 | ll.addHead(1); 190 | ll.addHead(2); 191 | ll.addHead(3); 192 | ll.print(); 193 | 194 | ll.removeTail(); 195 | ll.print(); 196 | } 197 | 198 | /* 199 | 3 2 1 200 | 3 2 201 | */ 202 | 203 | main1(); 204 | main2(); 205 | main3(); 206 | main4(); 207 | -------------------------------------------------------------------------------- /LinkedList/DoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | class DLLNode { 2 | constructor(v, nxt, prv) { 3 | this.value = v; 4 | this.next = nxt; 5 | this.prev = prv; 6 | } 7 | } 8 | 9 | class DoublyLinkedList { 10 | constructor() { 11 | this.head = null; 12 | this.tail = null; 13 | this.length = 0; 14 | } 15 | 16 | size() { 17 | return this.length; 18 | } 19 | 20 | isEmpty() { 21 | return this.length === 0; 22 | } 23 | 24 | peek() { 25 | if (this.isEmpty()) 26 | throw new Error("EmptyListError"); 27 | return this.head.value; 28 | } 29 | 30 | /* Other methods */ 31 | 32 | addHead(value) { 33 | const newNode = new DLLNode(value, null, null); 34 | if (this.length === 0) { 35 | this.tail = this.head = newNode; 36 | } else { 37 | this.head.prev = newNode; 38 | newNode.next = this.head; 39 | this.head = newNode; 40 | } 41 | this.length++; 42 | } 43 | 44 | addTail(value) { 45 | const newNode = new DLLNode(value, null, null); 46 | if (this.length === 0) { 47 | this.head = this.tail = newNode; 48 | } else { 49 | newNode.prev = this.tail; 50 | this.tail.next = newNode; 51 | this.tail = newNode; 52 | } 53 | this.length++; 54 | } 55 | 56 | removeHead() { 57 | if (this.isEmpty()) 58 | throw new Error("EmptyListError"); 59 | const value = this.head.value; 60 | this.head = this.head.next; 61 | if (this.head == null) 62 | this.tail = null; 63 | else 64 | this.head.prev = null; 65 | this.length--; 66 | return value; 67 | } 68 | 69 | removeNode(key) { 70 | let curr = this.head; 71 | if (curr == null) 72 | return false; 73 | 74 | if (curr.value === key) { 75 | this.head = this.head.next; 76 | this.length--; 77 | if (this.head != null) 78 | this.head.prev = null; 79 | else 80 | this.tail = null; 81 | return true; 82 | } 83 | 84 | while (curr.next != null) { 85 | if (curr.next.value === key) { 86 | curr.next = curr.next.next; 87 | if (curr.next == null) 88 | this.tail = curr; 89 | else 90 | curr.next.prev = curr; 91 | this.length--; 92 | return true; 93 | } 94 | curr = curr.next; 95 | } 96 | return false; 97 | } 98 | 99 | find(key) { 100 | let temp = this.head; 101 | while (temp != null) { 102 | if (temp.value === key) 103 | return true; 104 | temp = temp.next; 105 | } 106 | return false; 107 | } 108 | 109 | freeList() { 110 | this.head = null; 111 | this.tail = null; 112 | this.length = 0; 113 | } 114 | 115 | print() { 116 | let temp = this.head; 117 | while (temp != null) { 118 | process.stdout.write(`${temp.value} `); 119 | temp = temp.next; 120 | } 121 | process.stdout.write("\n"); 122 | } 123 | 124 | sortedInsert(value) { 125 | const temp = new DLLNode(value, null, null); 126 | let curr = this.head; 127 | 128 | if (curr == null) { // empty list 129 | this.head = temp; 130 | this.tail = temp; 131 | return; 132 | } 133 | 134 | if (this.head.value > value) { // First node. 135 | temp.next = this.head; 136 | this.head.prev = temp; 137 | this.head = temp; 138 | return; 139 | } 140 | 141 | while (curr.next != null && curr.next.value < value) { 142 | curr = curr.next; 143 | } 144 | 145 | if (curr.next == null) { // Last node 146 | this.tail = temp; 147 | temp.prev = curr; 148 | curr.next = temp; 149 | } else { 150 | temp.next = curr.next; 151 | temp.prev = curr; 152 | curr.next = temp; 153 | temp.next.prev = temp; 154 | } 155 | } 156 | 157 | reverseList() { 158 | let curr = this.head; 159 | let tempNode; 160 | while (curr != null) { 161 | tempNode = curr.next; 162 | curr.next = curr.prev; 163 | curr.prev = tempNode; 164 | if (curr.prev == null) { 165 | this.tail = this.head; 166 | this.head = curr; 167 | return; 168 | } 169 | curr = curr.prev; 170 | } 171 | } 172 | 173 | removeDuplicate() { 174 | let curr = this.head; 175 | while (curr != null) { 176 | if ((curr.next != null) && curr.value == curr.next.value) { 177 | curr.next = curr.next.next; 178 | if(curr.next != null) 179 | curr.next.prev = curr; 180 | else 181 | this.tail = curr; 182 | } else { 183 | curr = curr.next; 184 | } 185 | } 186 | } 187 | 188 | copyListReversed() { 189 | const dll = new DoublyLinkedList(); 190 | let curr = this.head; 191 | while (curr != null) { 192 | dll.addHead(curr.value); 193 | curr = curr.next; 194 | } 195 | return dll; 196 | } 197 | 198 | copyList() { 199 | const dll = new DoublyLinkedList(); 200 | let curr = this.head; 201 | while (curr != null) { 202 | dll.addTail(curr.value); 203 | curr = curr.next; 204 | } 205 | return dll; 206 | } 207 | } 208 | 209 | // Testing code. 210 | function main1() { 211 | let ll = new DoublyLinkedList(); 212 | ll.addHead(1); 213 | ll.addHead(2); 214 | ll.addHead(3); 215 | ll.print(); 216 | console.log("size : " + ll.size()); 217 | console.log("isEmpty : " + ll.isEmpty()); 218 | 219 | ll.removeHead(); 220 | ll.print(); 221 | console.log(ll.find(2)); 222 | } 223 | /* 224 | 3 2 1 225 | size : 3 226 | isEmpty : false 227 | 2 1 228 | true 229 | */ 230 | 231 | function main2() { 232 | let ll = new DoublyLinkedList(); 233 | ll.sortedInsert(1); 234 | ll.sortedInsert(2); 235 | ll.sortedInsert(3); 236 | ll.print(); 237 | ll.sortedInsert(1); 238 | ll.sortedInsert(2); 239 | ll.sortedInsert(3); 240 | ll.print(); 241 | ll.removeDuplicate(); 242 | ll.print(); 243 | } 244 | /* 245 | 1 2 3 246 | 1 1 2 2 3 3 247 | 1 2 3 248 | */ 249 | 250 | function main3() { 251 | let ll = new DoublyLinkedList(); 252 | ll.addHead(1); 253 | ll.addHead(2); 254 | ll.addHead(3); 255 | ll.print(); 256 | 257 | let l2 = ll.copyList(); 258 | l2.print(); 259 | let l3 = ll.copyListReversed(); 260 | l3.print(); 261 | } 262 | /* 263 | 3 2 1 264 | 3 2 1 265 | 1 2 3 266 | */ 267 | 268 | function main4() { 269 | let ll = new DoublyLinkedList(); 270 | ll.addHead(1); 271 | ll.addHead(2); 272 | ll.addHead(3); 273 | ll.print(); 274 | 275 | ll.removeNode(2); 276 | ll.print(); 277 | } 278 | 279 | /* 280 | 3 2 1 281 | 3 1 282 | */ 283 | 284 | function main5() { 285 | let ll = new DoublyLinkedList(); 286 | ll.addHead(1); 287 | ll.addHead(2); 288 | ll.addHead(3); 289 | ll.print(); 290 | ll.reverseList(); 291 | ll.print(); 292 | } 293 | 294 | /* 295 | 3 2 1 296 | 1 2 3 297 | */ 298 | 299 | main1(); 300 | main2(); 301 | main3(); 302 | main4(); 303 | main5(); -------------------------------------------------------------------------------- /LinkedList/Poly.js: -------------------------------------------------------------------------------- 1 | class PolyNode { 2 | constructor(c, p) { 3 | this.coeff = c; 4 | this.pow = p; 5 | this.next = null; 6 | } 7 | } 8 | 9 | class Polynomial { 10 | constructor(coeffs=[], pows=[], size=0) { 11 | this.head = null; 12 | this.tail = null 13 | let temp = null; 14 | for (let i = 0; i < size; i++) { 15 | temp = new PolyNode(coeffs[i], pows[i]); 16 | if (this.head == null) 17 | this.head = this.tail = temp; 18 | else { 19 | this.tail.next = temp; 20 | this.tail = this.tail.next; 21 | } 22 | } 23 | } 24 | 25 | add(poly2) { 26 | let poly = new Polynomial() 27 | let p1 = this.head; 28 | let p2 = poly2.head; 29 | let temp; 30 | while (p1 != null || p2 != null) { 31 | if (p1 == null || (p2 != null && p1.pow < p2.pow)) { 32 | temp = new PolyNode(p2.coeff, p2.pow); 33 | p2 = p2.next; 34 | } else if (p2 == null || p1.pow > p2.pow) { 35 | temp = new PolyNode(p1.coeff, p1.pow); 36 | p1 = p1.next; 37 | } else if (p1.pow == p2.pow) { 38 | temp = new PolyNode(p1.coeff + p2.coeff, p1.pow); 39 | p1 = p1.next; 40 | p2 = p2.next; 41 | } 42 | 43 | if (poly.head == null) 44 | poly.head = poly.tail = temp; 45 | else { 46 | poly.tail.next = temp; 47 | poly.tail = poly.tail.next; 48 | } 49 | } 50 | return poly; 51 | } 52 | 53 | print() { 54 | let head = this.head; 55 | while (head != null) { 56 | process.stdout.write(head.coeff + "x^" + head.pow); 57 | if (head.next != null) 58 | process.stdout.write(" + "); 59 | head = head.next; 60 | } 61 | console.log(); 62 | } 63 | } 64 | // Testing code. 65 | function main11() { 66 | let c1 = [6, 5, 4]; 67 | let p1 = [2, 1, 0]; 68 | let s1 = c1.length; 69 | let first = new Polynomial(c1, p1, s1); 70 | first.print(); 71 | 72 | let c2 = [3, 2, 1]; 73 | let p2 = [3, 1, 0]; 74 | let s2 = c2.length; 75 | let second = new Polynomial(c2, p2, s2); 76 | second.print(); 77 | 78 | let sum = first.add(second); 79 | sum.print(); 80 | } 81 | 82 | main11(); 83 | 84 | /* 85 | 6x^2 + 5x^1 + 4x^0 86 | 3x^3 + 2x^1 + 1x^0 87 | 3x^3 + 6x^2 + 7x^1 + 5x^0 88 | */ 89 | -------------------------------------------------------------------------------- /Queue/Dequeue.js: -------------------------------------------------------------------------------- 1 | 2 | class Deque { 3 | constructor() { 4 | this.arr = ([]); 5 | } 6 | 7 | size() { 8 | return this.arr.length; 9 | } 10 | 11 | isEmpty() { 12 | return this.arr.length === 0 13 | } 14 | 15 | add(val) { 16 | this.arr.push(val); 17 | } 18 | 19 | remove() { 20 | return this.arr.shift(); 21 | } 22 | 23 | front() { 24 | return this.arr[0] 25 | } 26 | 27 | back() { 28 | return this.arr[this.arr.length - 1] 29 | } 30 | 31 | removeLast() { 32 | return this.arr.pop() 33 | } 34 | } 35 | 36 | // Testing code. 37 | const que = new Deque(); 38 | que.add(1); 39 | que.add(2); 40 | que.add(3); 41 | que.add(4); 42 | while (que.isEmpty() === false) { 43 | console.log(que.removeLast()); 44 | console.log(que.remove()); 45 | } -------------------------------------------------------------------------------- /Queue/Queue.js: -------------------------------------------------------------------------------- 1 | 2 | class Queue { 3 | constructor() { 4 | this.arr = []; 5 | } 6 | 7 | add(value) { 8 | this.arr.push(value); 9 | } 10 | 11 | remove() { 12 | return this.arr.shift(); 13 | } 14 | 15 | front() { 16 | return this.arr[0]; 17 | } 18 | 19 | isEmpty() { 20 | return this.arr.length === 0 21 | } 22 | 23 | size() { 24 | return this.arr.length 25 | } 26 | 27 | print() { 28 | console.log(this.arr); 29 | } 30 | } 31 | 32 | // Testing code. 33 | const que = new Queue(); 34 | que.add(1); 35 | que.add(2); 36 | que.add(3); 37 | que.print(); 38 | console.log("isEmpty : " + que.isEmpty()); 39 | console.log("size : " + que.size()); 40 | console.log("Queue remove : " + que.remove()); 41 | console.log("Queue remove : " + que.remove()); 42 | 43 | /* 44 | [ 1, 2, 3 ] 45 | isEmpty : false 46 | size : 3 47 | Queue remove : 1 48 | Queue remove : 2 49 | */ -------------------------------------------------------------------------------- /Queue/QueueHalf.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.frontIndex = 0; 4 | this.arr = []; 5 | } 6 | 7 | add(value) { 8 | this.arr.push(value); 9 | } 10 | 11 | remove() { 12 | const value = this.arr[this.frontIndex]; 13 | this.frontIndex++; 14 | if (this.arr.length > 0 && this.frontIndex * 2 >= this.arr.length) { 15 | this.arr = this.arr.slice(this.frontIndex); 16 | this.frontIndex = 0; 17 | } 18 | return value; 19 | } 20 | 21 | isEmpty() { 22 | return (this.arr.length - this.frontIndex) === 0; 23 | } 24 | 25 | length() { 26 | return (this.arr.length - this.frontIndex); 27 | } 28 | } 29 | 30 | // Testing code. 31 | const que = new Queue(); 32 | for (let i = 0; i < 20; i++) { 33 | que.add(i); 34 | } 35 | for (let i = 0; i < 22; i++) { 36 | console.log(que.remove()); 37 | } -------------------------------------------------------------------------------- /Queue/QueueLL.js: -------------------------------------------------------------------------------- 1 | class QueueNode { 2 | constructor(v, n) { 3 | this.value = v; 4 | this.next = n; 5 | } 6 | } 7 | 8 | class Queue { 9 | constructor() { 10 | this.head = null; 11 | this.tail = null; 12 | this.length = 0; 13 | } 14 | 15 | size() { 16 | return this.length; 17 | } 18 | 19 | isEmpty() { 20 | return this.length === 0; 21 | } 22 | 23 | peek() { 24 | if (this.isEmpty()) 25 | throw new Error("StackEmptyError"); 26 | return this.head.value; 27 | } 28 | 29 | add(value) { 30 | const temp = new QueueNode(value, null); 31 | if (this.head == null) 32 | this.head = this.tail = temp; 33 | else { 34 | this.tail.next = temp; 35 | this.tail = temp; 36 | } 37 | this.length++; 38 | } 39 | 40 | remove() { 41 | if (this.isEmpty()) 42 | throw new Error("StackEmptyError"); 43 | const value = this.head.value; 44 | this.head = this.head.next; 45 | this.length--; 46 | return value; 47 | } 48 | 49 | print() { 50 | let output = "", temp = this.head; 51 | while (temp != null) { 52 | output += `${temp.value} ` 53 | temp = temp.next; 54 | } 55 | console.log(output); 56 | } 57 | } 58 | 59 | // Testing code. 60 | const que = new Queue(); 61 | que.add(1); 62 | que.add(2); 63 | que.add(3); 64 | que.print(); 65 | console.log("isEmpty : " + que.isEmpty()); 66 | console.log("size : " + que.size()); 67 | console.log("Queue remove : " + que.remove()); 68 | console.log("Queue remove : " + que.remove()); 69 | 70 | /* 71 | 1 2 3 72 | isEmpty : false 73 | size : 3 74 | Queue remove : 1 75 | Queue remove : 2 76 | */ -------------------------------------------------------------------------------- /Queue/QueueUsingStack.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.stk1 = []; 4 | this.stk2 = []; 5 | } 6 | 7 | length() { 8 | return (this.stk1.length + this.stk2.length); 9 | } 10 | 11 | isEmpty() { 12 | return (this.stk1.length + this.stk2.length) === 0; 13 | } 14 | 15 | add(value) { 16 | this.stk1.push(value); 17 | } 18 | 19 | remove() { 20 | let value; 21 | if (this.stk2.length > 0) { 22 | return this.stk2.pop(); 23 | } 24 | while (this.stk1.length > 0) { 25 | value = this.stk1.pop(); 26 | this.stk2.push(value); 27 | } 28 | return this.stk2.pop(); 29 | } 30 | } 31 | 32 | // Testing code. 33 | const que = new Queue(); 34 | que.add(1); 35 | que.add(2); 36 | que.add(3); 37 | while (que.isEmpty() === false) 38 | console.log(que.remove()); 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Data-Structures-and-Algorithms-using-JavaScript 2 | 3 | This is the code repository of book **Data Structures & Algorithms using Javascript**. 4 | 5 | ![alt text](https://m.media-amazon.com/images/P/B0BL3X4G4Z.jpg) 6 | 7 | 8 | **About The Book** 9 | - This textbook provides in depth coverage of various Data Structures and Algorithms. 10 | - Concepts are discussed in easy to understand manner. 11 | - Large number of diagrams are provided to grasp concepts easily. 12 | - Time and Space complexities of various algorithms are discussed. 13 | - Helpful for interviews preparation and competitive coding. 14 | - Large number of interview questions are solved. 15 | - Javascript solutions are provided with input and output. 16 | - Guide you through how to solve new problems in programming interview of various software companies. 17 | 18 | 19 | **Table of Contents** 20 | - Chapter 0: How to use this book. 21 | - Chapter 1: Algorithms Analysis 22 | - Chapter 2: Approach to solve algorithm design problems 23 | - Chapter 3: Abstract Data Type & Javascript Collections 24 | - Chapter 4: Searching 25 | - Chapter 5: Sorting 26 | - Chapter 6: Linked List 27 | - Chapter 7: Stack 28 | - Chapter 8: Queue 29 | - Chapter 9: Tree 30 | - Chapter 10: Priority Queue 31 | - Chapter 11: Hash-Table 32 | - Chapter 12: Graphs 33 | - Chapter 13: String Algorithms 34 | - Chapter 14: Algorithm Design Techniques 35 | - Chapter 15: Brute Force Algorithm 36 | - Chapter 16: Greedy Algorithm 37 | - Chapter 17: Divide & Conquer 38 | - Chapter 18: Dynamic Programming 39 | - Chapter 19: Backtracking 40 | - Chapter 20: Complexity Theory 41 | 42 | 43 | -------------------------------------------------------------------------------- /Searching/BitManipulation.js: -------------------------------------------------------------------------------- 1 | function andEx(a, b) { 2 | return a & b; 3 | } 4 | 5 | function orEx(a, b) { 6 | return a | b; 7 | } 8 | 9 | function xorEx(a, b) { 10 | return a ^ b; 11 | } 12 | 13 | function leftShiftEx(a) { 14 | return a << 1; // multiply by 2 15 | } 16 | 17 | function rightShiftEx(a) { 18 | return a >> 1; // divide by 2 19 | } 20 | 21 | function bitReversalEx(a) { 22 | return ~a; 23 | } 24 | 25 | function twoComplementEx(a) { 26 | return -a; 27 | } 28 | 29 | function kthBitCheck(a, k) { 30 | return (a & 1 << (k - 1)) > 0; 31 | } 32 | 33 | function kthBitSet(a, k) { 34 | return (a | 1 << (k - 1)); 35 | } 36 | 37 | function kthBitReset(a, k) { 38 | return (a & ~(1 << (k - 1))); 39 | } 40 | 41 | function kthBitToggle(a, k) { 42 | return (a ^ (1 << (k - 1))); 43 | } 44 | 45 | function rightMostBit(a) { 46 | return a & -a; 47 | } 48 | 49 | function resetRightMostBit(a) { 50 | return a & (a - 1); 51 | } 52 | 53 | function isPowerOf2(a) { 54 | if ((a & (a - 1)) == 0) { 55 | return true; 56 | } else { 57 | return false; 58 | } 59 | } 60 | 61 | function countBits(a) { 62 | let count = 0; 63 | while (a > 0) { 64 | count += 1; 65 | a = a & (a - 1); 66 | } 67 | return count; 68 | } 69 | 70 | // Testing code. 71 | let a = 4; 72 | let b = 8; 73 | console.log(andEx(a, b)); 74 | console.log(orEx(a, b)); 75 | console.log(xorEx(a, b)); 76 | console.log(leftShiftEx(a)); // multiply by 2 77 | console.log(rightShiftEx(a)); // divide by 2 78 | console.log(bitReversalEx(a)); 79 | console.log(twoComplementEx(a)); 80 | console.log(kthBitCheck(a, 3)); 81 | console.log(kthBitSet(a, 2)); 82 | console.log(kthBitReset(a, 3)); 83 | console.log(kthBitToggle(a, 3)); 84 | console.log(rightMostBit(a)); 85 | console.log(resetRightMostBit(a)); 86 | console.log(isPowerOf2(a)); 87 | for (let i = 0; i < 10; i++) { 88 | console.log(i + " bit count : " + countBits(i)); 89 | } 90 | 91 | 92 | /* 93 | 0 94 | 12 95 | 12 96 | 8 97 | 2 98 | -5 99 | -4 100 | true 101 | 6 102 | 0 103 | 0 104 | 4 105 | 0 106 | true 107 | */ 108 | 109 | /* 110 | 0 bit count : 0 111 | 1 bit count : 1 112 | 2 bit count : 1 113 | 3 bit count : 2 114 | 4 bit count : 1 115 | 5 bit count : 2 116 | 6 bit count : 2 117 | 7 bit count : 3 118 | 8 bit count : 1 119 | 9 bit count : 2 120 | */ -------------------------------------------------------------------------------- /Sorting/BubbleSort.js: -------------------------------------------------------------------------------- 1 | function bubbleSort(arr, compare) { 2 | const size = arr.length; 3 | let temp; 4 | for (let i = 0; i < (size - 1); i++) { 5 | for (let j = 0; j < size - i - 1; j++) { 6 | if (compare(arr[j], arr[j + 1])) { 7 | temp = arr[j]; 8 | arr[j] = arr[j + 1]; 9 | arr[j + 1] = temp; 10 | } 11 | } 12 | } 13 | } 14 | 15 | function bubbleSort2(arr, compare) { 16 | const size = arr.length; 17 | let temp; 18 | let swapped = 1; 19 | for (let i = 0; i < (size - 1) && swapped === 1; i++) { 20 | swapped = 0; 21 | for (let j = 0; j < size - i - 1; j++) { 22 | if (compare(arr[j], arr[j + 1])) { 23 | temp = arr[j]; 24 | arr[j] = arr[j + 1]; 25 | arr[j + 1] = temp; 26 | swapped = 1; 27 | } 28 | } 29 | } 30 | } 31 | 32 | less = (value1, value2) => value1 < value2; 33 | greater = (value1, value2) => value1 > value2; 34 | 35 | // Testing code. 36 | const array = [9, 1, 8, 2, 7, 3, 6, 4, 5]; 37 | bubbleSort(array, greater); 38 | console.log(JSON.stringify(array)); 39 | 40 | const array2 = [9, 1, 8, 2, 7, 3, 6, 4, 5]; 41 | bubbleSort(array2, less); 42 | console.log(JSON.stringify(array2)); 43 | 44 | const array3 = [9, 1, 8, 2, 7, 3, 6, 4, 5]; 45 | bubbleSort2(array3, greater); 46 | console.log(JSON.stringify(array3)); 47 | 48 | /* 49 | [1,2,3,4,5,6,7,8,9] 50 | [9,8,7,6,5,4,3,2,1] 51 | [1,2,3,4,5,6,7,8,9] 52 | */ -------------------------------------------------------------------------------- /Sorting/BucketSort.js: -------------------------------------------------------------------------------- 1 | function bucketSort(arr, maxValue) { 2 | let numBucket = 5; 3 | bucketSortUtil(arr, maxValue, numBucket); 4 | } 5 | 6 | function bucketSortUtil(arr, maxValue, numBucket) { 7 | let length = arr.length; 8 | if (length == 0) { 9 | return; 10 | } 11 | let bucket = new Array(); // Create empty buckets 12 | 13 | for (let i = 0; i < numBucket; i++) { 14 | (bucket.push(new Array()) > 0); 15 | } 16 | 17 | let div = parseInt(Math.ceil( maxValue / numBucket)); 18 | 19 | // Add elements into the buckets 20 | for (let i = 0; i < length; i++) { 21 | if (arr[i] < 0 || arr[i] > maxValue) { 22 | console.log("Value out of range."); 23 | return; 24 | } 25 | 26 | let bucketIndex = (parseInt(arr[i] / div)); 27 | 28 | // Maximum value will be assigned to last bucket. 29 | if (bucketIndex >= numBucket) 30 | bucketIndex = numBucket - 1; 31 | bucket[bucketIndex].push(arr[i]); 32 | } 33 | 34 | // bucketSort the elements of each bucket. 35 | for (let i = 0; i < numBucket; i++) { 36 | bucket[i].sort(function(a, b){return a - b;}); 37 | } 38 | 39 | // Populate output from the bucketSorted subarray. 40 | let index = 0, count = 0; 41 | for (let i = 0; i < numBucket; i++) { 42 | let temp = bucket[i]; 43 | count = temp.length; 44 | for (let j = 0; j < count; j++) { 45 | arr[index++] = temp[j]; 46 | } 47 | } 48 | } 49 | 50 | // Testing code. 51 | let array = [1, 34, 7, 99, 5, 23, 45, 88, 77, 19, 91, 100]; 52 | let maxValue = 100; 53 | bucketSort(array, maxValue); 54 | console.log(JSON.stringify(array)); 55 | 56 | /* 57 | [1,5,7,19,23,34,45,77,88,91,99,100] 58 | */ -------------------------------------------------------------------------------- /Sorting/CountSort.js: -------------------------------------------------------------------------------- 1 | function countSort(arr, lowerRange, upperRange) { 2 | let i = 0, j = 0; 3 | let size = arr.length; 4 | let range = upperRange - lowerRange; 5 | let count = Array(range).fill(0); 6 | for (i = 0; i < size; i++) { 7 | count[arr[i] - lowerRange]++; 8 | } 9 | for (i = 0; i < range; i++) { 10 | for (; count[i] > 0; count[i]--) { 11 | arr[j++] = i + lowerRange; 12 | } 13 | } 14 | } 15 | 16 | // Testing code. 17 | let array = [23, 24, 22, 21, 26, 25, 27, 28, 21, 21]; 18 | countSort(array, 20, 30); 19 | console.log(JSON.stringify(array)); 20 | 21 | /* 22 | [21,21,21,22,23,24,25,26,27,28] 23 | 24 | */ -------------------------------------------------------------------------------- /Sorting/InsertionSort.js: -------------------------------------------------------------------------------- 1 | function insertionSort(arr, compare) { 2 | const size = arr.length; 3 | let temp; 4 | for (let i = 1; i < size; i++) { 5 | temp = arr[i]; 6 | for (var j = i; j > 0 && compare(arr[j - 1], temp); j--) { 7 | arr[j] = arr[j - 1]; 8 | } 9 | arr[j] = temp; 10 | } 11 | } 12 | 13 | greater = (value1, value2) => value1 > value2; 14 | 15 | // Testing code. 16 | const array = [9, 1, 8, 2, 7, 3, 6, 4, 5]; 17 | insertionSort(array, greater); 18 | console.log(JSON.stringify(array)); 19 | 20 | /* 21 | [1,2,3,4,5,6,7,8,9] 22 | */ -------------------------------------------------------------------------------- /Sorting/MergeSort.js: -------------------------------------------------------------------------------- 1 | 2 | function merge(arr, tempArray, lowerIndex, middleIndex, upperIndex, compare) { 3 | let lowerStart = lowerIndex; 4 | const lowerStop = middleIndex; 5 | let upperStart = middleIndex + 1; 6 | const upperStop = upperIndex; 7 | let count = lowerIndex; 8 | while (lowerStart <= lowerStop && upperStart <= upperStop) { 9 | if (compare(arr[lowerStart], arr[upperStart])) { 10 | tempArray[count++] = arr[lowerStart++]; 11 | } else { 12 | tempArray[count++] = arr[upperStart++]; 13 | } 14 | } 15 | while (lowerStart <= lowerStop) { 16 | tempArray[count++] = arr[lowerStart++]; 17 | } 18 | while (upperStart <= upperStop) { 19 | tempArray[count++] = arr[upperStart++]; 20 | } 21 | for (let i = lowerIndex; i <= upperIndex; i++) { 22 | arr[i] = tempArray[i]; 23 | } 24 | } 25 | 26 | function mergeSortUtil(arr, tempArray, lowerIndex, upperIndex, compare) { 27 | if (lowerIndex >= upperIndex) { 28 | return; 29 | } 30 | const middleIndex = Math.floor((lowerIndex + upperIndex) / 2); 31 | mergeSortUtil(arr, tempArray, lowerIndex, middleIndex, compare); 32 | mergeSortUtil(arr, tempArray, middleIndex + 1, upperIndex, compare); 33 | merge(arr, tempArray, lowerIndex, middleIndex, upperIndex, compare); 34 | } 35 | 36 | function mergeSort(arr, compare) { 37 | const size = arr.length; 38 | const tempArray = new Array(size); 39 | mergeSortUtil(arr, tempArray, 0, size - 1, compare); 40 | } 41 | 42 | less = (value1, value2) => value1 < value2; 43 | greater = (value1, value2) => value1 > value2; 44 | 45 | // Testing code. 46 | const array = [3, 4, 2, 1, 6, 5, 7, 8]; 47 | mergeSort(array, less); 48 | console.log(JSON.stringify(array)); 49 | 50 | /* 51 | [1,2,3,4,5,6,7,8] 52 | 53 | */ -------------------------------------------------------------------------------- /Sorting/QuickSelect.js: -------------------------------------------------------------------------------- 1 | function swap(arr, first, second) { 2 | const temp = arr[first]; 3 | arr[first] = arr[second]; 4 | arr[second] = temp; 5 | } 6 | 7 | function quickSelectUtil(arr, lower, upper, k) { 8 | if (upper <= lower) 9 | return; 10 | 11 | const pivot = arr[lower]; 12 | const start = lower; 13 | const stop = upper; 14 | while (lower < upper) { 15 | while (arr[lower] <= pivot && lower < upper) { 16 | lower++; 17 | } 18 | while (arr[upper] > pivot && lower <= upper) { 19 | upper--; 20 | } 21 | if (lower < upper) { 22 | swap(arr, upper, lower); 23 | } 24 | } 25 | swap(arr, upper, start); 26 | if (k < upper) 27 | quickSelectUtil(arr, start, upper - 1, k); 28 | if (k > upper) 29 | quickSelectUtil(arr, upper + 1, stop, k); 30 | } 31 | 32 | function quickSelect(arr, k) { 33 | quickSelectUtil(arr, 0, arr.length - 1, k - 1); 34 | return arr[k - 1]; 35 | } 36 | 37 | // Testing code. 38 | const array = [3, 4, 2, 1, 6, 5, 7, 8, 10, 9]; 39 | quickSelect(array, 5); 40 | console.log(`Fifth value is : ${array[4]}`); 41 | 42 | /* 43 | Fifth value is : 5 44 | */ -------------------------------------------------------------------------------- /Sorting/QuickSort.js: -------------------------------------------------------------------------------- 1 | function quickSortUtil(arr, lower, upper) { 2 | if (upper <= lower) 3 | return; 4 | 5 | const pivot = arr[lower]; 6 | const start = lower; 7 | const stop = upper; 8 | while (lower < upper) { 9 | while (arr[lower] <= pivot && lower < upper) { 10 | lower++; 11 | } 12 | while (arr[upper] > pivot && lower <= upper) { 13 | upper--; 14 | } 15 | if (lower < upper) { 16 | swap(arr, upper, lower); 17 | } 18 | } 19 | swap(arr, upper, start); 20 | quickSortUtil(arr, start, upper - 1); 21 | quickSortUtil(arr, upper + 1, stop); 22 | } 23 | 24 | function quickSort(arr) { 25 | const size = arr.length; 26 | quickSortUtil(arr, 0, size - 1); 27 | } 28 | 29 | swap = (arr, first, second) => { 30 | const temp = arr[first]; 31 | arr[first] = arr[second]; 32 | arr[second] = temp; 33 | } 34 | 35 | // Testing code. 36 | const array = [3, 4, 2, 1, 6, 5, 7, 8]; 37 | quickSort(array); 38 | console.log(JSON.stringify(array)); 39 | 40 | /* 41 | [1,2,3,4,5,6,7,8] 42 | */ -------------------------------------------------------------------------------- /Sorting/RadixSort.js: -------------------------------------------------------------------------------- 1 | function getMax(arr, n) { 2 | let max = arr[0]; 3 | for (let i = 1; i < n; i++) { 4 | if (max < arr[i]) { 5 | max = arr[i]; 6 | } 7 | } 8 | return max; 9 | } 10 | 11 | function countSort(arr, n, dividend) { 12 | let temp = [...arr]; // Clone array 13 | let count = Array(10).fill(0); 14 | // Store count of occurrences in count array. 15 | // (number / dividend) % 10 is used to find the working digit. 16 | for (let i = 0; i < n; i++) { 17 | count[(parseInt(temp[i] / dividend)) % 10]++; 18 | } 19 | // Change count[i] so that count[i] contains 20 | // number of elements till index i in output. 21 | for (let i = 1; i < 10; i++) { 22 | count[i] += count[i - 1]; 23 | } 24 | // Copy content to input arr. 25 | for (let i = n - 1; i >= 0; i--) { 26 | arr[count[(parseInt(temp[i] / dividend)) % 10] - 1] = temp[i]; 27 | count[(parseInt(temp[i] / dividend)) % 10]--; 28 | } 29 | } 30 | 31 | function radixSort(arr) { 32 | let n = arr.length; 33 | let m = getMax(arr, n); 34 | // Counting sort for every digit. 35 | // The dividend passed is used to calculate current working digit. 36 | for (let div = 1; parseInt(m / div) > 0; div *= 10) { 37 | countSort(arr, n, div); 38 | } 39 | } 40 | 41 | // Testing code. 42 | let array = [100, 49, 65, 91, 702, 29, 4, 55]; 43 | radixSort(array); 44 | console.log(JSON.stringify(array)); 45 | 46 | /* 47 | [4,29,49,55,65,91,100,702] 48 | */ -------------------------------------------------------------------------------- /Sorting/SelectionSort.js: -------------------------------------------------------------------------------- 1 | less = (value1, value2) => value1 < value2; 2 | 3 | greater = (value1, value2) => value1 > value2; 4 | 5 | function selectionSort(arr, compare) { 6 | const size = arr.length; 7 | let max; 8 | let temp; 9 | for (let i = 0; i < size - 1; i++) { 10 | max = 0; 11 | for (let j = 1; j < size - i; j++) { 12 | if (compare(arr[j], arr[max])) { 13 | max = j; 14 | } 15 | } 16 | temp = arr[size - 1 - i]; 17 | arr[size - 1 - i] = arr[max]; 18 | arr[max] = temp; 19 | } 20 | } 21 | 22 | function selectionSort2(arr, compare) { 23 | const size = arr.length; 24 | let min; 25 | let temp; 26 | for (let i = 0; i < size - 1; i++) { 27 | min = i; 28 | for (let j = i + 1; j < size; j++) { 29 | if (compare(arr[min], arr[j])) { 30 | min = j; 31 | } 32 | } 33 | temp = arr[i]; 34 | arr[i] = arr[min]; 35 | arr[min] = temp; 36 | } 37 | } 38 | 39 | // Testing code. 40 | const array = [4, 5, 3, 2, 6, 7, 1, 8, 9, 10]; 41 | selectionSort(array, greater); 42 | console.log(JSON.stringify(array)); 43 | 44 | const array2 = [9, 1, 8, 2, 7, 3, 6, 4, 5]; 45 | selectionSort2(array2, less); 46 | console.log(JSON.stringify(array2)); 47 | 48 | /* 49 | [1,2,3,4,5,6,7,8,9,10] 50 | [9,8,7,6,5,4,3,2,1] 51 | */ -------------------------------------------------------------------------------- /Sorting/ShellSort.js: -------------------------------------------------------------------------------- 1 | greater = (value1, value2) => value1 > value2; 2 | 3 | function shellSort(arr) { 4 | let n = arr.length; 5 | // Gap starts with n/2 and half in each iteration. 6 | for (let gap = parseInt(n / 2); gap > 0; gap = parseInt(gap / 2)) { 7 | // Do a gapped insertion sort. 8 | for (let i = gap; i < n; i += 1) { 9 | let curr = arr[i]; 10 | // Shift elements of already sorted list to find right position for curr value. 11 | let j = 0; 12 | for (j = i; j >= gap && greater(arr[j - gap], curr); j -= gap) { 13 | arr[j] = arr[j - gap]; 14 | } 15 | // Put current value in its correct location 16 | arr[j] = curr; 17 | } 18 | } 19 | } 20 | 21 | // Testing code. 22 | let array = [36, 32, 11, 6, 19, 31, 17, 3]; 23 | shellSort(array); 24 | console.log(JSON.stringify(array)); 25 | 26 | /* 27 | [3,6,11,17,19,31,32,36] 28 | */ -------------------------------------------------------------------------------- /Stack/Stack.js: -------------------------------------------------------------------------------- 1 | class Stack { 2 | constructor(capacity) { 3 | this.arr = []; 4 | } 5 | /* other methods */ 6 | 7 | size() { 8 | return this.arr.length; 9 | } 10 | 11 | isEmpty() { 12 | return (this.arr.length === 0); 13 | } 14 | 15 | push(value) { 16 | this.arr.push(value); 17 | } 18 | 19 | top() { 20 | if (this.isEmpty()) { 21 | throw new Error("Stack Empty Exception"); 22 | } 23 | return this.arr[this.arr.length-1]; 24 | } 25 | 26 | pop() { 27 | if (this.isEmpty()) { 28 | throw new Error("Stack Empty Exception"); 29 | } 30 | return this.arr.pop(); 31 | } 32 | 33 | print() { 34 | console.log(this.arr); 35 | } 36 | } 37 | 38 | // Testing code. 39 | const s = new Stack(); 40 | s.push(1); 41 | s.push(2); 42 | s.push(3); 43 | s.print(); 44 | console.log(s.pop()); 45 | console.log(s.pop()); 46 | console.log(s.pop()); 47 | 48 | /* 49 | [ 1, 2, 3 ] 50 | 3 51 | 2 52 | 1 53 | */ -------------------------------------------------------------------------------- /Stack/StackLL.js: -------------------------------------------------------------------------------- 1 | class StackNode { 2 | constructor(v, n) { 3 | this.value = v; 4 | this.next = n; 5 | } 6 | }; 7 | 8 | class Stack { 9 | constructor() { 10 | this.head = null; 11 | this.length = 0; 12 | } 13 | 14 | size() { 15 | return this.length; 16 | } 17 | 18 | isEmpty() { 19 | return this.length === 0; 20 | } 21 | 22 | peek() { 23 | if (this.isEmpty()) { 24 | throw new Error("StackEmptyError"); 25 | } 26 | return this.head.value; 27 | } 28 | 29 | push(value) { 30 | this.head = new StackNode(value, this.head); 31 | this.length++; 32 | } 33 | 34 | pop() { 35 | if (this.isEmpty()) { 36 | throw new Error("StackEmptyError"); 37 | } 38 | const value = this.head.value; 39 | this.head = this.head.next; 40 | this.length--; 41 | return value; 42 | } 43 | 44 | insertAtBottom(value) { 45 | if (this.isEmpty()) { 46 | this.push(value); 47 | } else { 48 | const temp = this.pop(); 49 | this.insertAtBottom(value); 50 | this.push(temp); 51 | } 52 | } 53 | 54 | print() { 55 | let out = ""; 56 | let temp = this.head; 57 | while (temp != null) { 58 | out += temp.value + " "; 59 | temp = temp.next; 60 | }; 61 | console.log(out); 62 | } 63 | } 64 | 65 | // Testing code. 66 | const s = new Stack(); 67 | s.push(1); 68 | s.push(2); 69 | s.push(3); 70 | s.print(); 71 | console.log(s.pop()); 72 | console.log(s.pop()); -------------------------------------------------------------------------------- /Stack/TwoStack.js: -------------------------------------------------------------------------------- 1 | /* REMOVE FROM BOOK */ 2 | class TwoStack { 3 | constructor() { 4 | this.MAX_SIZE = 1000; 5 | this.top1 = -1; 6 | this.top2 = this.MAX_SIZE; 7 | this.data = new Array(this.MAX_SIZE); 8 | } 9 | 10 | push1(value) { 11 | if (this.top1 < this.top2 - 1) { 12 | this.data[++this.top1] = value; 13 | } else { 14 | console.log("Stack is Full!"); 15 | } 16 | } 17 | 18 | push2(value) { 19 | if (this.top1 < this.top2 - 1) { 20 | this.data[--this.top2] = value; 21 | } else { 22 | console.log("Stack is Full!"); 23 | } 24 | } 25 | 26 | pop1() { 27 | if (this.top1 >= 0) { 28 | const value = this.data[this.top1--]; 29 | return value; 30 | } else { 31 | console.log("Stack Empty!"); 32 | } 33 | return -999; 34 | } 35 | 36 | pop2() { 37 | if (this.top2 < this.MAX_SIZE) { 38 | const value = this.data[this.top2++]; 39 | return value; 40 | } else { 41 | console.log("Stack Empty!"); 42 | } 43 | return -999; 44 | } 45 | } 46 | 47 | // Testing code. 48 | const st = new TwoStack(); 49 | st.push1(1); 50 | st.push1(2); 51 | st.push1(3); 52 | st.push2(4); 53 | st.push2(5); 54 | st.push2(6); 55 | console.log("stk1 pop: " + st.pop1()); 56 | console.log("stk1 pop: " + st.pop1()); 57 | console.log("stk2 pop: " + st.pop2()); 58 | console.log("stk2 pop: " + st.pop2()); 59 | 60 | /* 61 | stk1 pop: 3 62 | stk1 pop: 2 63 | stk2 pop: 6 64 | stk2 pop: 5 65 | */ 66 | -------------------------------------------------------------------------------- /String/StringAlgo.js: -------------------------------------------------------------------------------- 1 | function matchExpUtil(exp, str, i, j) { 2 | if (i === exp.length && j === str.length) { 3 | return true; 4 | } 5 | if ((i === exp.length && j !== str.length) || 6 | (i !== exp.length && j === str.length)) { 7 | return false; 8 | } 9 | if (exp[i] === '?' || exp[i] === str[j]) { 10 | return matchExpUtil(exp, str, i + 1, j + 1); 11 | } 12 | if (exp[i] === '*') { 13 | return matchExpUtil(exp, str, i + 1, j) 14 | || matchExpUtil(exp, str, i, j + 1) 15 | || matchExpUtil(exp, str, i + 1, j + 1); 16 | } 17 | return false; 18 | } 19 | 20 | function matchExp(exp, str) { 21 | return matchExpUtil(exp, str, 0, 0); 22 | } 23 | 24 | // Testing code. 25 | function test1() { 26 | console.log(matchExp("hello*", "helloworld")); 27 | console.log(matchExp("hello?d", "hellowd")); 28 | console.log(matchExp("hello*hemant", "helloworldfsdfsdfdsfhemant")); 29 | console.log(matchExp("*hemantj", "helloworldfsdfsdfdsfhemant")); 30 | } 31 | 32 | test1(); 33 | /* 34 | true 35 | true 36 | true 37 | false 38 | */ 39 | 40 | function matchPattern(source, pattern) { 41 | let iSource = 0; 42 | let iPattern = 0; 43 | const sourceLen = source.length; 44 | const patternLen = pattern.length; 45 | for (iSource = 0; iSource < sourceLen; iSource++) { 46 | if (source[iSource] === pattern[iPattern]) { 47 | iPattern++; 48 | } 49 | if (iPattern === patternLen) { 50 | return true; 51 | } 52 | } 53 | return false; 54 | } 55 | 56 | // Testing code. 57 | function test2() { 58 | console.log(matchPattern("hellofskdlfjsdlfjsldjflksdworld", "helloworld")); 59 | console.log(matchPattern("hellod", "hellowd")); 60 | console.log(matchPattern("hello*xxxxxxxxxxhemantxxxxxxxxxxxx", "hellnt")); 61 | console.log() 62 | } 63 | 64 | test2(); 65 | /* 66 | true 67 | false 68 | true 69 | */ 70 | 71 | function isPrime(n) { 72 | let answer = (n > 1) ? true : false; 73 | for (let i = 2; i * i <= n; ++i) { 74 | if (n % i === 0) { 75 | answer = false; 76 | break; 77 | } 78 | } 79 | return answer; 80 | } 81 | 82 | // Testing code. 83 | function test3() { 84 | process.stdout.write("Prime numbers under 100 :: "); 85 | for (let i = 0; i < 100; i++) { 86 | if (isPrime(i)) 87 | process.stdout.write(`${i} `); 88 | } 89 | console.log() 90 | } 91 | 92 | test3(); 93 | /* 94 | Prime numbers under 100 :: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 95 | */ 96 | 97 | function isUniqueChar(str) { 98 | const bitarr = new Array(26).fill(0); 99 | const size = str.length; 100 | const small = "a".charCodeAt(0); 101 | const big = "A".charCodeAt(0); 102 | 103 | for (let i = 0; i < size; i++) { 104 | let c = str.charCodeAt(i); 105 | if ((big <= c) && (big + 26 >= c)) { 106 | c = (c - big); 107 | } else if ((small <= c) && (small + 26 >= c)) { 108 | c = (c - small); 109 | } else { 110 | console.log("Unknown Char."); 111 | return false; 112 | } 113 | if (bitarr[c] !== 0) { 114 | console.log("Duplicate detected."); 115 | return false; 116 | } 117 | bitarr[c] = 1; 118 | } 119 | console.log("No duplicate detected."); 120 | return true; 121 | } 122 | 123 | // Testing code. 124 | function test5() { 125 | isUniqueChar("aple"); 126 | isUniqueChar("apple"); 127 | } 128 | 129 | test5(); 130 | /* 131 | No duplicate detected. 132 | Duplicate detected. 133 | */ 134 | 135 | function ToUpper(s) { 136 | ascii = s.charCodeAt(0) 137 | if (ascii >= 97 && ascii <= (97 + 25)) { 138 | s = String.fromCharCode(ascii - 32); 139 | } 140 | return s; 141 | } 142 | 143 | function ToLower(s) { 144 | ascii = s.charCodeAt(0) 145 | if (ascii >= 65 && ascii <= (65 + 25)) { 146 | s = String.fromCharCode(ascii + 32); 147 | } 148 | return s; 149 | } 150 | 151 | function LowerUpper(s) { 152 | ascii = s.charCodeAt(0) 153 | if (ascii >= 97 && ascii <= (97 + 25)) { 154 | s = String.fromCharCode(ascii - 32); 155 | } 156 | else if (ascii >= 65 && ascii <= (65 + 25)) { 157 | s = String.fromCharCode(ascii + 32); 158 | } 159 | return s; 160 | } 161 | 162 | // Testing code. 163 | function test6() { 164 | console.log(ToLower('A')); 165 | console.log(ToUpper('a')); 166 | console.log(LowerUpper('s')); 167 | console.log(LowerUpper('S')); 168 | } 169 | 170 | test6(); 171 | /* 172 | a 173 | A 174 | S 175 | s 176 | */ 177 | 178 | function isPermutation(s1, s2) { 179 | const count = new Array(256).fill(0); 180 | const length = s1.length; 181 | if (s2.length !== length) { 182 | return false; 183 | } 184 | 185 | for (let i = 0; i < length; i++) { 186 | count[s1.charCodeAt(i)]++; 187 | count[s2.charCodeAt(i)]--; 188 | } 189 | 190 | for (let i = 0; i < length; i++) { 191 | if (count[s1.charCodeAt(i)] !== 0) { 192 | return false; 193 | } 194 | } 195 | 196 | return true; 197 | } 198 | 199 | // Testing code. 200 | function test7() { 201 | console.log("isPermutation :", isPermutation("apple", "plepa")); 202 | console.log("isPermutation :", isPermutation("appleb", "plepaa")); 203 | } 204 | 205 | test7(); 206 | /* 207 | isPermutation : true 208 | isPermutation : false 209 | */ 210 | 211 | function isPalindrome(str) { 212 | let i = 0; 213 | let j = str.length - 1; 214 | while ((i < j) && (str[i] == str[j])) { 215 | i++; 216 | j--; 217 | } 218 | 219 | if (i < j) { 220 | console.log(str, "is not a Palindrome"); 221 | return false; 222 | } else { 223 | console.log(str, "is a Palindrome"); 224 | return true; 225 | } 226 | } 227 | 228 | // Testing code. 229 | function test8() { 230 | isPalindrome("hello"); 231 | isPalindrome("oyo"); 232 | } 233 | 234 | test8(); 235 | /* 236 | hello is not a Palindrome 237 | eoloe is a Palindrome 238 | */ 239 | 240 | function pow(x, n) { 241 | let value; 242 | if (n === 0) { 243 | return (1); 244 | } else if (n % 2 === 0) { 245 | value = pow(x, Math.floor(n / 2)); 246 | return (value * value); 247 | } else { 248 | value = pow(x, Math.floor(n / 2)); 249 | return (x * value * value); 250 | } 251 | } 252 | 253 | // Testing code. 254 | function test9() { 255 | console.log(pow(5, 2)); 256 | } 257 | 258 | test9(); 259 | // 25 260 | 261 | function myStrcmp(a, b) { 262 | let index = 0; 263 | const len1 = a.length; 264 | const len2 = b.length; 265 | let minlen = len1; 266 | 267 | if (len1 > len2) { 268 | minlen = len2; 269 | } 270 | while ((index < minlen) && (a[index] === b[index])) { 271 | index++; 272 | } 273 | if (index === len1 && index === len2) { 274 | return 0; 275 | } else if (len1 === index) { 276 | return -1; 277 | } else if (len2 === index) { 278 | return 1; 279 | } else { 280 | return (a.charCodeAt(index) - b.charCodeAt(index)); 281 | } 282 | } 283 | 284 | // Testing code. 285 | function test10() { 286 | console.log("StrCmp returns :", myStrcmp("apple", "appke")); 287 | console.log("StrCmp returns :", myStrcmp("apple", "apple")); 288 | console.log("StrCmp returns :", myStrcmp("apple", "appme")); 289 | } 290 | 291 | test10(); 292 | 293 | /* 294 | StrCmp returns : 1 295 | StrCmp returns : 0 296 | StrCmp returns : -1 297 | */ 298 | 299 | 300 | function reverseString(str) { 301 | const a = (str).split(''); 302 | reverseStringUtil(a); 303 | const expn = a.join(''); 304 | return expn; 305 | } 306 | 307 | function reverseStringUtil(a) { 308 | let lower = 0; 309 | let upper = a.length - 1; 310 | let tempChar; 311 | 312 | while (lower < upper) { 313 | tempChar = a[lower]; 314 | a[lower] = a[upper]; 315 | a[upper] = tempChar; 316 | lower++; 317 | upper--; 318 | } 319 | } 320 | 321 | function reverseStringUtil2(a, lower, upper) { 322 | let tempChar; 323 | 324 | while (lower < upper) { 325 | tempChar = a[lower]; 326 | a[lower] = a[upper]; 327 | a[upper] = tempChar; 328 | lower++; 329 | upper--; 330 | } 331 | } 332 | 333 | function reverseWords(str) { 334 | const a = str.split(""); 335 | const length = a.length; 336 | let lower; 337 | let upper = -1; 338 | lower = 0; 339 | for (let i = 0; i <= length; i++) { 340 | if (a[i] === ' ') { 341 | reverseStringUtil2(a, lower, upper); 342 | lower = i + 1; 343 | upper = i; 344 | } else { 345 | upper++; 346 | } 347 | } 348 | reverseStringUtil2(a, lower, upper - 1); 349 | reverseStringUtil2(a, 0, length - 1); 350 | return a.join(""); 351 | } 352 | 353 | // Testing code. 354 | function test11() { 355 | console.log(reverseString("apple")); 356 | console.log(reverseWords("hello world")); 357 | } 358 | 359 | test11(); 360 | /* 361 | elppa 362 | world hello 363 | */ 364 | 365 | function printAnagram(str) { 366 | const size = str.length; 367 | const arr = str.split(''); 368 | printAnagramUtil(arr, 0, size); 369 | } 370 | 371 | function swapch(a, x, y) { 372 | let temp = a[x]; 373 | a[x] = a[y]; 374 | a[y] = temp; 375 | } 376 | 377 | function printAnagramUtil(arr, i, size) { 378 | if (i == size) { 379 | console.log(arr.join("")); 380 | return; 381 | } 382 | 383 | for (let j = i; j < size; j++) { 384 | swapch(arr, i, j); 385 | printAnagramUtil(arr, i + 1, size); 386 | swapch(arr, i, j); 387 | } 388 | } 389 | 390 | // Testing code. 391 | function test12() { 392 | printAnagram("123"); 393 | } 394 | 395 | test12(); 396 | /* 397 | 123 398 | 132 399 | 213 400 | 231 401 | 321 402 | 312 403 | */ 404 | 405 | function shuffle(str) { 406 | const ar = str.split(''); 407 | const n = Math.floor(ar.length / 2); 408 | let count = 0; 409 | let k = 1; 410 | let temp; 411 | let temp2; 412 | for (let i = 1; i < n; i = i + 2) { 413 | temp = ar[i]; 414 | k = i; 415 | do { 416 | k = (2 * k) % (2 * n - 1); 417 | temp2 = temp; 418 | temp = ar[k]; 419 | ar[k] = temp2; 420 | count++; 421 | } while (i !== k); 422 | 423 | if (count === (2 * n - 2)) { 424 | break; 425 | } 426 | } 427 | return ar.join("") 428 | } 429 | 430 | // Testing code. 431 | function test13() { 432 | console.log(shuffle("ABCDE12345")); 433 | } 434 | 435 | test13(); 436 | //A1B2C3D4E5 437 | 438 | function addBinary(first, second) { 439 | let size1 = first.length; 440 | let size2 = second.length; 441 | let totalIndex; 442 | let total; 443 | if (size1 > size2) { 444 | total = new Array(size1 + 2).fill(null); 445 | totalIndex = size1; 446 | } else { 447 | total = new Array(size2 + 2).fill(null); 448 | totalIndex = size2; 449 | } 450 | total[totalIndex + 1] = ''; 451 | let carry = 0; 452 | size1--; 453 | size2--; 454 | while (size1 >= 0 || size2 >= 0) { 455 | const firstValue = (size1 < 0) ? 0 : first[size1] - '0'; 456 | const secondValue = (size2 < 0) ? 0 : second[size2] - '0'; 457 | let sum = firstValue + secondValue + carry; 458 | carry = sum >> 1; 459 | sum = sum & 1; 460 | total[totalIndex] = (sum === 0) ? '0' : '1'; 461 | totalIndex--; 462 | size1--; 463 | size2--; 464 | } 465 | total[totalIndex] = (carry === 0) ? '0' : '1'; 466 | return total.join(""); 467 | } 468 | 469 | // Testing code. 470 | function test14() { 471 | console.log(addBinary("1000", "11111111")); 472 | } 473 | test14(); 474 | //100000111 -------------------------------------------------------------------------------- /String/StringMatching.js: -------------------------------------------------------------------------------- 1 | function BruteForceSearch(text, pattern) { 2 | if ((typeof text != 'string') || (typeof pattern != 'string')) 3 | throw new Error('invalid overload'); 4 | 5 | let i = 0; 6 | let j = 0; 7 | const n = text.length; 8 | const m = pattern.length; 9 | 10 | while (i <= n - m) { 11 | j = 0; 12 | while (j < m && pattern[j] === text[i + j]) 13 | j++; 14 | 15 | if (j === m) 16 | return (i); 17 | 18 | i++; 19 | } 20 | return -1; 21 | } 22 | 23 | function RobinKarp(text, pattern) { 24 | 25 | if ((typeof text != 'string') || (typeof pattern != 'string')) 26 | throw new Error('invalid overload'); 27 | 28 | const n = text.length; 29 | const m = pattern.length; 30 | let i; 31 | let j; 32 | const prime = 101; 33 | let powm = 1; 34 | let TextHash = 0; 35 | let PatternHash = 0; 36 | if (m === 0 || m > n) { 37 | return -1; 38 | } 39 | 40 | for (i = 0; i < m - 1; i++) { 41 | powm = (powm << 1) % prime; 42 | } 43 | 44 | for (i = 0; i < m; i++) { 45 | PatternHash = ((PatternHash << 1) + (pattern[i]).charCodeAt(0)) % prime; 46 | TextHash = ((TextHash << 1) + (text[i]).charCodeAt(0)) % prime; 47 | } 48 | 49 | for (i = 0; i <= (n - m); i++) { 50 | if (TextHash === PatternHash) { 51 | for (j = 0; j < m; j++) { 52 | if (text[i + j] !== pattern[j]) { 53 | break; 54 | } 55 | } 56 | if (j === m) 57 | return i; 58 | } 59 | TextHash = (((TextHash - (text[i]).charCodeAt(0) * powm) << 1) + (text[i + m]).charCodeAt(0)) 60 | % prime; 61 | if (TextHash < 0) { 62 | TextHash = (TextHash + prime); 63 | } 64 | } 65 | return -1; 66 | } 67 | 68 | function KMPPreprocess(pattern, ShiftArr) { 69 | const m = pattern.length; 70 | let i = 0; 71 | let j = -1; 72 | ShiftArr[i] = -1; 73 | while (i < m) { 74 | while (j >= 0 && pattern[i] !== pattern[j]) { 75 | j = ShiftArr[j]; 76 | } 77 | i++; 78 | j++; 79 | ShiftArr[i] = j; 80 | } 81 | } 82 | 83 | function KMP(text, pattern) { 84 | if ((typeof text != 'string') || (typeof pattern != 'string')) 85 | throw new Error('invalid overload'); 86 | 87 | let i = 0; 88 | let j = 0; 89 | const n = text.length; 90 | const m = pattern.length; 91 | const ShiftArr = new Array(m + 1); 92 | 93 | KMPPreprocess(pattern, ShiftArr); 94 | 95 | while (i < n) { 96 | while (j >= 0 && text[i] !== pattern[j]) 97 | j = ShiftArr[j]; 98 | i++; 99 | j++; 100 | if (j === m) { 101 | return (i - m); 102 | } 103 | } 104 | return -1; 105 | } 106 | 107 | function KMPFindCount(text, pattern) { 108 | if ((typeof text != 'string') || (typeof pattern != 'string')) 109 | throw new Error('invalid overload'); 110 | 111 | let i = 0; 112 | let j = 0; 113 | let count = 0; 114 | const n = text.length; 115 | const m = pattern.length; 116 | const ShiftArr = new Array(m + 1); 117 | 118 | KMPPreprocess(pattern, ShiftArr); 119 | 120 | while (i < n) { 121 | while (j >= 0 && text[i] !== pattern[j]) { 122 | j = ShiftArr[j]; 123 | } 124 | i++; 125 | j++; 126 | if (j === m) { 127 | count++; 128 | j = ShiftArr[j]; 129 | } 130 | } 131 | return count; 132 | } 133 | 134 | // Testing code. 135 | const st1 = "hello, world!"; 136 | const st2 = "world"; 137 | console.log(`Using BruteForceSearch pattern found at index : ${BruteForceSearch(st1, st2)}`); 138 | console.log(`Using RobinKarp pattern found at index : ${RobinKarp(st1, st2)}`); 139 | console.log(`Using KMP pattern found at index : ${KMP(st1, st2)}`); 140 | 141 | const str3 = "Only time will tell if we stand the test of time" 142 | console.log('Frequency of "time" is ', KMPFindCount(str3, "time")) 143 | 144 | /* 145 | Using BruteForceSearch pattern found at index : 7 146 | Using RobinKarp pattern found at index : 7 147 | Using KMP pattern found at index : 7 148 | Frequency of "time" is 2 149 | */ -------------------------------------------------------------------------------- /String/StringTree.js: -------------------------------------------------------------------------------- 1 | class StringTreeNode { 2 | constructor() { 3 | this.value = 0; 4 | this.count = 0; 5 | this.left = null; 6 | this.right = null; 7 | } 8 | } 9 | 10 | class StringTree { 11 | constructor() { 12 | this.root = null; 13 | } 14 | 15 | print() { 16 | this.printUtil(this.root); 17 | } 18 | 19 | printUtil(curr) { 20 | if (curr != null) { 21 | console.log(` value is ::${curr.value}`); 22 | console.log(` count is :: ${curr.count}`); 23 | this.printUtil(curr.left); 24 | this.printUtil(curr.right); 25 | } 26 | } 27 | 28 | insert(value) { 29 | this.root = this.insertUtil(value, this.root); 30 | } 31 | 32 | insertUtil(value, curr) { 33 | let compare; 34 | if (curr == null) { 35 | curr = new StringTreeNode(this); 36 | curr.value = value; 37 | curr.left = curr.right = null; 38 | curr.count = 1; 39 | } else { 40 | compare = curr.value.localeCompare(value); 41 | if (compare === 0) 42 | curr.count++; 43 | else if (compare === 1) 44 | curr.left = this.insertUtil(value, curr.left); 45 | else 46 | curr.right = this.insertUtil(value, curr.right); 47 | } 48 | return curr; 49 | } 50 | 51 | freeTree() { 52 | this.root = null; 53 | } 54 | 55 | find(value) { 56 | const ret = this.findUtil(this.root, value); 57 | return ret; 58 | } 59 | 60 | findUtil(curr, value) { 61 | let compare; 62 | if (curr == null) 63 | return false; 64 | 65 | compare = curr.value.localeCompare(value); 66 | if (compare === 0) 67 | return true; 68 | else { 69 | if (compare === 1) 70 | return this.findUtil(curr.left, value); 71 | else 72 | return this.findUtil(curr.right, value); 73 | } 74 | } 75 | 76 | frequency(value) { 77 | return this.frequencyUtil(this.root, value); 78 | } 79 | 80 | frequencyUtil(curr, value) { 81 | let compare; 82 | if (curr == null) 83 | return 0; 84 | 85 | compare = curr.value.localeCompare(value); 86 | if (compare === 0) 87 | return curr.count; 88 | else { 89 | if (compare > 0) 90 | return this.frequencyUtil(curr.left, value); 91 | else 92 | return this.frequencyUtil(curr.right, value); 93 | } 94 | } 95 | } 96 | 97 | // Testing code. 98 | const tt = new StringTree(); 99 | tt.insert("banana"); 100 | tt.insert("apple"); 101 | tt.insert("mango"); 102 | console.log("Apple Found :", tt.find("apple")); 103 | console.log("Grapes Found :", tt.find("grapes")); 104 | console.log("Banana Found :", tt.find("banana")); 105 | 106 | /* 107 | Apple Found : true 108 | Grapes Found : false 109 | Banana Found : true 110 | */ -------------------------------------------------------------------------------- /String/Stringclass.js: -------------------------------------------------------------------------------- 1 | const str1 = "hello"; 2 | const str2 = "hello"; 3 | const str3 = "Hello"; 4 | console.log(`str1 equals str2 :${str1 === str2}`); 5 | console.log(`str1 equals str3 :${str1 === str3}`); -------------------------------------------------------------------------------- /String/TST.js: -------------------------------------------------------------------------------- 1 | class TSTNode { 2 | constructor(d) { 3 | this.data = d; 4 | this.isLastChar = false; 5 | this.left = this.equal = this.right = null; 6 | } 7 | } 8 | 9 | class TST { 10 | constructor() { 11 | this.root = null; 12 | } 13 | 14 | insert(word) { 15 | this.root = this.insertUtil(this.root, word, 0); 16 | } 17 | 18 | insertUtil(curr, word, wordIndex) { 19 | if (curr == null) 20 | curr = new TSTNode(word.charAt(wordIndex)); 21 | 22 | if ((word.charAt(wordIndex)).charCodeAt(0) < (curr.data).toString().charCodeAt(0)) 23 | curr.left = this.insertUtil(curr.left, word, wordIndex); 24 | else if ((word.charAt(wordIndex)).charCodeAt(0) > (curr.data).toString().charCodeAt(0)) 25 | curr.right = this.insertUtil(curr.right, word, wordIndex); 26 | else { 27 | if (wordIndex < word.length - 1) 28 | curr.equal = this.insertUtil(curr.equal, word, wordIndex + 1); 29 | else 30 | curr.isLastChar = true; 31 | } 32 | return curr; 33 | } 34 | 35 | findUtil(curr, word, wordIndex) { 36 | if (curr == null) 37 | return false; 38 | if ((word.charAt(wordIndex)).charCodeAt(0) < (curr.data).toString().charCodeAt(0)) 39 | return this.findUtil(curr.left, word, wordIndex); 40 | else if ((word.charAt(wordIndex)).charCodeAt(0) > (curr.data).toString().charCodeAt(0)) 41 | return this.findUtil(curr.right, word, wordIndex); 42 | else { 43 | if (wordIndex === word.length - 1) 44 | return curr.isLastChar; 45 | return this.findUtil(curr.equal, word, wordIndex + 1); 46 | } 47 | } 48 | 49 | find(word) { 50 | const ret = this.findUtil(this.root, word, 0); 51 | return ret; 52 | } 53 | } 54 | 55 | // Testing code. 56 | const tt = new TST(); 57 | tt.insert("banana"); 58 | tt.insert("apple"); 59 | tt.insert("mango"); 60 | console.log("Apple Found :", tt.find("apple")); 61 | console.log("Grapes Found :", tt.find("grapes")); 62 | console.log("Banana Found :", tt.find("banana")); 63 | 64 | /* 65 | Apple Found : true 66 | Grapes Found : false 67 | Banana Found : true 68 | */ -------------------------------------------------------------------------------- /String/Trie.js: -------------------------------------------------------------------------------- 1 | class TrieNode { 2 | constructor(c) { 3 | this.child = new Array(Trie.CharCount).fill(null); 4 | this.isLastChar = false; 5 | this.ch = c; 6 | } 7 | } 8 | 9 | class Trie { 10 | constructor() { 11 | Trie.CharCount = 26; 12 | this.root = new TrieNode(' '); 13 | } 14 | 15 | insert(str) { 16 | if (str == null) { 17 | return this.root; 18 | } 19 | const temp = str.toString().toLowerCase(); 20 | return this.insertUtil(this.root, temp, 0); 21 | } 22 | 23 | insertUtil(curr, str, index) { 24 | if (curr == null) { 25 | curr = new TrieNode(this, str[index - 1]); 26 | } 27 | 28 | if (str.length === index) { 29 | curr.isLastChar = true; 30 | } else { 31 | curr.child[str[index].charCodeAt(0) - 'a'.charCodeAt(0)] = this.insertUtil(curr.child[str[index].charCodeAt(0) - 'a'.charCodeAt(0)], str, index + 1); 32 | } 33 | return curr; 34 | } 35 | 36 | remove(str) { 37 | if (str == null) { 38 | return; 39 | } 40 | str = str.toLowerCase(); 41 | this.removeUtil(this.root, str, 0); 42 | } 43 | 44 | removeUtil(curr, str, index) { 45 | if (curr == null) { 46 | return; 47 | } 48 | 49 | if (str.length === index) { 50 | if (curr.isLastChar) { 51 | curr.isLastChar = false; 52 | } 53 | return; 54 | } 55 | this.removeUtil(curr.child[str[index].charCodeAt(0) - 'a'.charCodeAt(0)], str, index + 1); 56 | } 57 | 58 | find(str) { 59 | if (str == null) { 60 | return false; 61 | } 62 | str = str.toLowerCase(); 63 | return this.findUtil(this.root, str, 0); 64 | } 65 | 66 | findUtil(curr, str, index) { 67 | if (curr == null) { 68 | return false; 69 | } 70 | if (str.length === index) { 71 | return curr.isLastChar; 72 | } 73 | return this.findUtil(curr.child[str[index].charCodeAt(0) - 'a'.charCodeAt(0)], str, index + 1); 74 | } 75 | } 76 | 77 | // Testing code. 78 | const tt = new Trie(); 79 | tt.insert("banana"); 80 | tt.insert("apple"); 81 | tt.insert("mango"); 82 | console.log("Apple Found :", tt.find("apple")); 83 | console.log("Grapes Found :", tt.find("grapes")); 84 | console.log("Banana Found :", tt.find("banana")); 85 | 86 | /* 87 | Apple Found : true 88 | Grapes Found : false 89 | Banana Found : true 90 | */ -------------------------------------------------------------------------------- /Tree/AVLTree.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(d, l, r) { 4 | this.data = d; 5 | this.left = l; 6 | this.right = r; 7 | this.height = 0; 8 | } 9 | } 10 | 11 | class AVLTree 12 | { 13 | constructor() { 14 | this.root = null; 15 | } 16 | 17 | height(n) { 18 | if (n == null) { 19 | return -1; 20 | } 21 | return n.height; 22 | } 23 | 24 | getBalance(node) { 25 | return (node == null) ? 0 : this.height(node.left) - this.height(node.right); 26 | } 27 | 28 | insert(data) { 29 | this.root = this.insertUtil(this.root, data); 30 | } 31 | 32 | insertUtil(node, data) { 33 | if (node == null) { 34 | return new Node(data, null, null); 35 | } 36 | if (node.data > data) { 37 | node.left = this.insertUtil(node.left, data); 38 | } else if (node.data < data) { 39 | node.right = this.insertUtil(node.right, data); 40 | } else { 41 | // Duplicate data not allowed 42 | return node; 43 | } 44 | node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; 45 | let balance = this.getBalance(node); 46 | if (balance > 1) { 47 | if (data < node.left.data) // Left Left Case 48 | { 49 | return this.rightRotate(node); 50 | } 51 | if (data > node.left.data) // Left Right Case 52 | { 53 | return this.leftRightRotate(node); 54 | } 55 | } 56 | if (balance < -1) { 57 | if (data > node.right.data) // Right Right Case 58 | { 59 | return this.leftRotate(node); 60 | } 61 | if (data < node.right.data) // Right Left Case 62 | { 63 | return this.rightLeftRotate(node); 64 | } 65 | } 66 | return node; 67 | } 68 | // Function to right rotate subtree rooted with x 69 | rightRotate(x) { 70 | let y = x.left; 71 | let T = y.right; 72 | // Rotation 73 | y.right = x; 74 | x.left = T; 75 | // Update heights 76 | x.height = Math.max(this.height(x.left), this.height(x.right)) + 1; 77 | y.height = Math.max(this.height(y.left), this.height(y.right)) + 1; 78 | // Return new root 79 | return y; 80 | } 81 | // Function to left rotate subtree rooted with x 82 | leftRotate(x) { 83 | let y = x.right; 84 | let T = y.left; 85 | // Rotation 86 | y.left = x; 87 | x.right = T; 88 | // Update heights 89 | x.height = Math.max(this.height(x.left), this.height(x.right)) + 1; 90 | y.height = Math.max(this.height(y.left), this.height(y.right)) + 1; 91 | // Return new root 92 | return y; 93 | } 94 | 95 | // Function to right then left rotate subtree rooted with x 96 | rightLeftRotate(x) { 97 | x.right = this.rightRotate(x.right); 98 | return this.leftRotate(x); 99 | } 100 | 101 | // Function to left then right rotate subtree rooted with x 102 | leftRightRotate(x) { 103 | x.left = this.leftRotate(x.left); 104 | return this.rightRotate(x); 105 | } 106 | 107 | delete(data) { 108 | this.root = this.deleteUtil(this.root, data); 109 | } 110 | 111 | deleteUtil(node, data) { 112 | if (node == null) { 113 | return null; 114 | } 115 | if (node.data == data) { 116 | if (node.left == null && node.right == null) { 117 | return null; 118 | } else if (node.left == null) { 119 | return node.right; 120 | } else if (node.right == null) { 121 | return node.left; 122 | } else { 123 | let minNode = this.findMin(node.right); 124 | node.data = minNode.data; 125 | node.right = this.deleteUtil(node.right, minNode.data); 126 | } 127 | } else { 128 | if (node.data > data) { 129 | node.left = this.deleteUtil(node.left, data); 130 | } else { 131 | node.right = this.deleteUtil(node.right, data); 132 | } 133 | } 134 | node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; 135 | let balance = this.getBalance(node); 136 | if (balance > 1) { 137 | if (data >= node.left.data) { // Left Left Case 138 | return this.rightRotate(node); 139 | } 140 | if (data < node.left.data) { // Left Right Case 141 | return this.leftRightRotate(node); 142 | } 143 | } 144 | if (balance < -1) { 145 | if (data <= node.right.data) { // Right Right Case 146 | return this.leftRotate(node); 147 | } 148 | if (data > node.right.data) { // Right Left Case 149 | return this.rightLeftRotate(node); 150 | } 151 | } 152 | return node; 153 | } 154 | 155 | findMin(curr) { 156 | let node = curr; 157 | if (node == null) { 158 | return null; 159 | } 160 | while (node.left != null) { 161 | node = node.left; 162 | } 163 | return node; 164 | } 165 | 166 | printTree() { 167 | this.printTreeUtil(this.root, "", false); 168 | console.log(); 169 | } 170 | 171 | printTreeUtil(node, indent, isLeft) { 172 | if (node == null) { 173 | return; 174 | } 175 | let out = ""; 176 | if (isLeft) { 177 | out += indent + "L:"; 178 | indent += "| "; 179 | } else { 180 | out += indent + "R:"; 181 | indent += " "; 182 | } 183 | console.log(out + node.data + "(" + node.height + ")"); 184 | this.printTreeUtil(node.left, indent, true); 185 | this.printTreeUtil(node.right, indent, false); 186 | } 187 | } 188 | 189 | // Testing code. 190 | let t = new AVLTree(); 191 | t.insert(1); 192 | t.insert(2); 193 | t.insert(3); 194 | t.insert(4); 195 | t.insert(5); 196 | t.insert(6); 197 | t.insert(7); 198 | t.insert(8); 199 | t.printTree(); 200 | /* 201 | R:4(3) 202 | L:2(1) 203 | | L:1(0) 204 | | R:3(0) 205 | R:6(2) 206 | L:5(0) 207 | R:7(1) 208 | R:8(0) 209 | 210 | */ 211 | t.delete(5); 212 | t.printTree(); 213 | /* 214 | R:4(2) 215 | L:2(1) 216 | | L:1(0) 217 | | R:3(0) 218 | R:7(1) 219 | L:6(0) 220 | R:8(0) 221 | 222 | */ 223 | t.delete(1); 224 | t.printTree(); 225 | /* 226 | R:4(2) 227 | L:2(1) 228 | | R:3(0) 229 | R:7(1) 230 | L:6(0) 231 | R:8(0) 232 | 233 | */ 234 | t.delete(2); 235 | t.printTree(); 236 | -------------------------------------------------------------------------------- /Tree/BinaryIndexTree.js: -------------------------------------------------------------------------------- 1 | class BinaryIndexTree 2 | { 3 | constructor(arr) { 4 | this.size = arr.length; 5 | this.BIT = Array(this.size + 1).fill(0); 6 | // Populating bit. 7 | for (let i = 0; i < this.size; i++) { 8 | this.update(i, arr[i]); 9 | } 10 | } 11 | 12 | set(arr, index, val) { 13 | let diff = val - arr[index]; 14 | arr[index] = val; 15 | // Difference is propagated. 16 | this.update(index, diff); 17 | } 18 | 19 | update(index, val) { 20 | // Index in bit is 1 more than the input array. 21 | index = index + 1; 22 | // Traverse to ancestors of nodes. 23 | while (index <= this.size) { 24 | // Add val to current node of Binary Index Tree. 25 | this.BIT[index] += val; 26 | // Next element which need to store val. 27 | index += index & (-index); 28 | } 29 | } 30 | 31 | // Range sum in the range start to end. 32 | rangeSum(start, end) { 33 | // Check for error conditions. 34 | if (start > end || start < 0 || end > this.size - 1) { 35 | console.log("Invalid Input."); 36 | return -1; 37 | } 38 | return this.prefixSum(end) - this.prefixSum(start - 1); 39 | } 40 | 41 | // Prefix sum in the range 0 to index. 42 | prefixSum(index) { 43 | let sum = 0; 44 | index = index + 1; 45 | // Traverse ancestors of Binary Index Tree nodes. 46 | while (index > 0) { 47 | // Add current element to sum. 48 | sum += this.BIT[index]; 49 | // Parent index calculation. 50 | index -= index & (-index); 51 | } 52 | return sum; 53 | } 54 | } 55 | 56 | // Testing code. 57 | let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; 58 | let tree = new BinaryIndexTree(arr); 59 | console.log("Sum of elements in range(0, 5): " + tree.prefixSum(5)); 60 | console.log("Sum of elements in range(2, 5): " + tree.rangeSum(2, 5)); 61 | // Set fourth element to 10. 62 | tree.set(arr, 3, 10); 63 | // Find sum after the value is updated 64 | console.log("Sum of elements in range(0, 5): " + tree.prefixSum(5)); 65 | 66 | /* 67 | Sum of elements in range(0, 5): 21 68 | Sum of elements in range(2, 5): 18 69 | Sum of elements in range(0, 5): 27 70 | */ -------------------------------------------------------------------------------- /Tree/RBTree.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(data, nullNode) { 4 | this.data = data; 5 | this.left = nullNode; 6 | this.right = nullNode; 7 | this.colour = true; // true for red, false for black. New node are red in colour. 8 | this.parent = nullNode; 9 | } 10 | } 11 | 12 | class RBTree 13 | { 14 | constructor() { 15 | this.NullNode = new Node(0, null); 16 | this.NullNode.colour = false; 17 | this.root = this.NullNode; 18 | } 19 | 20 | // To check whether node is of colour red or not. 21 | isRed(node) { 22 | return (node == null) ? false : (node.colour == true); 23 | } 24 | 25 | uncle(node) { 26 | // If no parent or grandparent, then no uncle 27 | if (node.parent == this.NullNode || node.parent.parent == this.NullNode) { 28 | return null; 29 | } 30 | if (node.parent == node.parent.parent.left) { 31 | // uncle on right 32 | return node.parent.parent.right; 33 | } else { 34 | // uncle on left 35 | return node.parent.parent.left; 36 | } 37 | } 38 | 39 | // Function to right rotate subtree rooted with x 40 | rightRotate(x) { 41 | let y = x.left; 42 | let T = y.right; 43 | // Rotation 44 | y.parent = x.parent; 45 | y.right = x; 46 | x.parent = y; 47 | x.left = T; 48 | if (T != this.NullNode) { 49 | T.parent = x; 50 | } 51 | if (x == this.root) { 52 | this.root = y; 53 | return y; 54 | } 55 | if (y.parent.left == x) { 56 | y.parent.left = y; 57 | } else { 58 | y.parent.right = y; 59 | } 60 | // Return new root 61 | return y; 62 | } 63 | 64 | // Function to left rotate subtree rooted with x 65 | leftRotate(x) { 66 | let y = x.right; 67 | let T = y.left; 68 | // Rotation 69 | y.parent = x.parent; 70 | y.left = x; 71 | x.parent = y; 72 | x.right = T; 73 | if (T != this.NullNode) { 74 | T.parent = x; 75 | } 76 | if (x == this.root) { 77 | this.root = y; 78 | return y; 79 | } 80 | if (y.parent.left == x) { 81 | y.parent.left = y; 82 | } else { 83 | y.parent.right = y; 84 | } 85 | // Return new root 86 | return y; 87 | } 88 | 89 | rightLeftRotate(node) { 90 | node.right = this.rightRotate(node.right); 91 | return this.leftRotate(node); 92 | } 93 | 94 | leftRightRotate(node) { 95 | node.left = this.leftRotate(node.left); 96 | return this.rightRotate(node); 97 | } 98 | 99 | find(data) { 100 | let curr = this.root; 101 | while (curr != this.NullNode) { 102 | if (curr.data == data) { 103 | return curr; 104 | } 105 | else if (curr.data > data) { 106 | curr = curr.left; 107 | } else { 108 | curr = curr.right; 109 | } 110 | } 111 | return null; 112 | } 113 | 114 | printTree() { 115 | this.printTreeUtil(this.root, "", false); 116 | console.log(); 117 | } 118 | 119 | printTreeUtil(node, indent, isLeft) { 120 | if (node == this.NullNode) { 121 | return; 122 | } 123 | let output = ""; 124 | if (isLeft) { 125 | output += indent + "L:"; 126 | indent += "| "; 127 | } else { 128 | output += indent + "R:"; 129 | indent += " "; 130 | } 131 | console.log(output + node.data + "(" + node.colour + ")"); 132 | this.printTreeUtil(node.left, indent, true); 133 | this.printTreeUtil(node.right, indent, false); 134 | } 135 | 136 | insert(data) { 137 | this.root = this.insertUtil(this.root, data); 138 | let temp = this.find(data); 139 | this.fixRedRed(temp); 140 | } 141 | 142 | insertUtil(node, data) { 143 | if (node == this.NullNode) { 144 | node = new Node(data, this.NullNode); 145 | } else if (node.data > data) { 146 | node.left = this.insertUtil(node.left, data); 147 | node.left.parent = node; 148 | } else if (node.data < data) { 149 | node.right = this.insertUtil(node.right, data); 150 | node.right.parent = node; 151 | } 152 | return node; 153 | } 154 | 155 | fixRedRed(x) { 156 | // if x is root colour it black and return 157 | if (x == this.root) { 158 | x.colour = false; 159 | return; 160 | } 161 | if (x.parent == this.NullNode || x.parent.parent == this.NullNode) { 162 | return; 163 | } 164 | // Initialize parent, grandparent, uncle 165 | let parent = x.parent; 166 | let grandparent = parent.parent; 167 | let uncle = this.uncle(x); 168 | let mid = null; 169 | if (parent.colour == false) { 170 | return; 171 | } 172 | // parent colour is red. gp is black. 173 | if (uncle != this.NullNode && uncle.colour == true) { 174 | // uncle and parent is red. 175 | parent.colour = false; 176 | uncle.colour = false; 177 | grandparent.colour = true; 178 | this.fixRedRed(grandparent); 179 | return; 180 | } 181 | // parent is red, uncle is black and gp is black. 182 | // Perform LR, LL, RL, RR 183 | if (parent == grandparent.left && x == parent.left) // LL 184 | { 185 | mid = this.rightRotate(grandparent); 186 | } else if (parent == grandparent.left && x == parent.right) // LR 187 | { 188 | mid = this.leftRightRotate(grandparent); 189 | } else if (parent == grandparent.right && x == parent.left) // RL 190 | { 191 | mid = this.rightLeftRotate(grandparent); 192 | } else if (parent == grandparent.right && x == parent.right) // RR 193 | { 194 | mid = this.leftRotate(grandparent); 195 | } 196 | mid.colour = false; 197 | mid.left.colour = true; 198 | mid.right.colour = true; 199 | } 200 | 201 | delete(data) { 202 | this.deleteUtil(this.root, data); 203 | } 204 | 205 | deleteUtil(node, key) { 206 | let z = this.NullNode; 207 | let x = null; 208 | let y = null; 209 | while (node != this.NullNode) { 210 | if (node.data == key) { 211 | z = node; 212 | break; 213 | } 214 | else if (node.data <= key) { 215 | node = node.right; 216 | } else { 217 | node = node.left; 218 | } 219 | } 220 | if (z == this.NullNode) { 221 | console.log("Couldn\'t find key in the tree"); 222 | return; 223 | } 224 | y = z; 225 | let yColour = y.colour; 226 | if (z.left == this.NullNode) { 227 | x = z.right; 228 | this.joinParentChild(z, z.right); 229 | } else if (z.right == this.NullNode) { 230 | x = z.left; 231 | this.joinParentChild(z, z.left); 232 | } else { 233 | y = this.minimum(z.right); 234 | yColour = y.colour; 235 | z.data = y.data; 236 | this.joinParentChild(y, y.right); 237 | x = y.right; 238 | } 239 | if (yColour == false) { 240 | if (x.colour == true) { 241 | x.colour = false; 242 | return; 243 | } else { 244 | this.fixDoubleBlack(x); 245 | } 246 | } 247 | } 248 | 249 | fixDoubleBlack(x) { 250 | if (x == this.root) { 251 | // Root node. 252 | return; 253 | } 254 | let sib = this.sibling(x); 255 | let parent = x.parent; 256 | if (sib == this.NullNode) { 257 | // No sibling double black shifted to parent. 258 | this.fixDoubleBlack(parent); 259 | } else { 260 | if (sib.colour == true) { 261 | // Sibling colour is red. 262 | parent.colour = true; 263 | sib.colour = false; 264 | if (sib.parent.left == sib) 265 | { 266 | // Sibling is left child. 267 | this.rightRotate(parent); 268 | } 269 | else 270 | { 271 | // Sibling is right child. 272 | this.leftRotate(parent); 273 | } 274 | this.fixDoubleBlack(x); 275 | } else { 276 | // Sibling colour is black 277 | // At least one child is red. 278 | if (sib.left.colour == true || sib.right.colour == true) 279 | { 280 | if (sib.parent.left == sib) 281 | { 282 | // Sibling is left child. 283 | if (sib.left != this.NullNode && sib.left.colour == true) 284 | { 285 | // left left case. 286 | sib.left.colour = sib.colour; 287 | sib.colour = parent.colour; 288 | this.rightRotate(parent); 289 | } 290 | else 291 | { 292 | // left right case. 293 | sib.right.colour = parent.colour; 294 | this.leftRotate(sib); 295 | this.rightRotate(parent); 296 | } 297 | } 298 | else 299 | { 300 | // Sibling is right child. 301 | if (sib.left != this.NullNode && sib.left.colour == true) 302 | { 303 | // right left case. 304 | sib.left.colour = parent.colour; 305 | this.rightRotate(sib); 306 | this.leftRotate(parent); 307 | } 308 | else 309 | { 310 | // right right case. 311 | sib.right.colour = sib.colour; 312 | sib.colour = parent.colour; 313 | this.leftRotate(parent); 314 | } 315 | } 316 | parent.colour = false; 317 | } 318 | else 319 | { 320 | // Both children black. 321 | sib.colour = true; 322 | if (parent.colour == false) 323 | { 324 | this.fixDoubleBlack(parent); 325 | } 326 | else 327 | { 328 | parent.colour = false; 329 | } 330 | } 331 | } 332 | } 333 | } 334 | 335 | sibling(node) { 336 | // sibling null if no parent 337 | if (node.parent == this.NullNode) { 338 | return null; 339 | } 340 | if (node.parent.left == node) { 341 | return node.parent.right; 342 | } 343 | return node.parent.left; 344 | } 345 | 346 | joinParentChild(u, v) { 347 | if (u.parent == this.NullNode) { 348 | this.root = v; 349 | } else if (u == u.parent.left) { 350 | u.parent.left = v; 351 | } else { 352 | u.parent.right = v; 353 | } 354 | v.parent = u.parent; 355 | } 356 | 357 | minimum(node) { 358 | while (node.left != this.NullNode) { 359 | node = node.left; 360 | } 361 | return node; 362 | } 363 | } 364 | 365 | // Testing code. 366 | let tree = new RBTree(); 367 | tree.insert(1); 368 | tree.insert(2); 369 | tree.insert(3); 370 | tree.insert(4); 371 | tree.insert(5); 372 | tree.insert(7); 373 | tree.insert(6); 374 | tree.insert(8); 375 | tree.insert(9); 376 | tree.printTree(); 377 | tree.delete(4); 378 | tree.printTree(); 379 | tree.delete(7); 380 | tree.printTree(); 381 | 382 | 383 | /* 384 | R:4(false) 385 | L:2(true) 386 | | L:1(false) 387 | | R:3(false) 388 | R:6(true) 389 | L:5(false) 390 | R:8(false) 391 | L:7(true) 392 | R:9(true) 393 | 394 | R:5(false) 395 | L:2(true) 396 | | L:1(false) 397 | | R:3(false) 398 | R:7(true) 399 | L:6(false) 400 | R:8(false) 401 | R:9(true) 402 | 403 | R:5(false) 404 | L:2(true) 405 | | L:1(false) 406 | | R:3(false) 407 | R:8(true) 408 | L:6(false) 409 | R:9(false) 410 | */ -------------------------------------------------------------------------------- /Tree/SPLAYTree.js: -------------------------------------------------------------------------------- 1 | class Node 2 | { 3 | constructor(d, l, r) { 4 | this.data = d; 5 | this.left = l; 6 | this.right = r; 7 | this.parent = null; 8 | } 9 | } 10 | 11 | class SPLAYTree 12 | { 13 | constructor() { 14 | this.root = null; 15 | } 16 | 17 | printTree() { 18 | this.printTreeUtil(this.root, "", false); 19 | console.log(); 20 | } 21 | 22 | printTreeUtil(node, indent, isLeft) { 23 | if (node == null) { 24 | return; 25 | } 26 | let output = ""; 27 | if (isLeft) { 28 | output += (indent + "L:"); 29 | indent += "| "; 30 | } else { 31 | output += (indent + "R:"); 32 | indent += " "; 33 | } 34 | console.log(output + node.data); 35 | this.printTreeUtil(node.left, indent, true); 36 | this.printTreeUtil(node.right, indent, false); 37 | } 38 | 39 | // Function to right rotate subtree rooted with x 40 | rightRotate(x) { 41 | let y = x.left; 42 | let T = y.right; 43 | // Rotation 44 | y.parent = x.parent; 45 | y.right = x; 46 | x.parent = y; 47 | x.left = T; 48 | if (T != null) { 49 | T.parent = x; 50 | } 51 | if (y.parent != null && y.parent.left == x) { 52 | y.parent.left = y; 53 | } else if (y.parent != null && y.parent.right == x) { 54 | y.parent.right = y; 55 | } 56 | // Return new root 57 | return y; 58 | } 59 | 60 | // Function to left rotate subtree rooted with x 61 | leftRotate(x) { 62 | let y = x.right; 63 | let T = y.left; 64 | // Rotation 65 | y.parent = x.parent; 66 | y.left = x; 67 | x.parent = y; 68 | x.right = T; 69 | if (T != null) { 70 | T.parent = x; 71 | } 72 | if (y.parent != null && y.parent.left == x) { 73 | y.parent.left = y; 74 | } else if (y.parent != null && y.parent.right == x) { 75 | y.parent.right = y; 76 | } 77 | // Return new root 78 | return y; 79 | } 80 | 81 | parent(node) { 82 | if (node == null || node.parent == null) { 83 | return null; 84 | } 85 | return node.parent; 86 | } 87 | 88 | splay(node) { 89 | let parent = null; 90 | let grand = null; 91 | while (node != this.root) { 92 | parent = this.parent(node); 93 | grand = this.parent(parent); 94 | if (parent == null) { 95 | // rotations had created new root, always last condition. 96 | this.root = node; 97 | } else if (grand == null) { 98 | // single rotation case. 99 | if (parent.left == node) 100 | { 101 | node = this.rightRotate(parent); 102 | } else { 103 | node = this.leftRotate(parent); 104 | } 105 | } else if (grand.left == parent && parent.left == node) { 106 | // Zig Zig case. 107 | this.rightRotate(grand); 108 | node = this.rightRotate(parent); 109 | } else if (grand.right == parent && parent.right == node) { 110 | // Zag Zag case. 111 | this.leftRotate(grand); 112 | node = this.leftRotate(parent); 113 | } else if (grand.left == parent && parent.right == node) { 114 | //Zig Zag case. 115 | this.leftRotate(parent); 116 | node = this.rightRotate(grand); 117 | } else if (grand.right == parent && parent.left == node) { 118 | // Zag Zig case. 119 | this.rightRotate(parent); 120 | node = this.leftRotate(grand); 121 | } 122 | } 123 | } 124 | 125 | find(data) { 126 | let curr = this.root; 127 | while (curr != null) { 128 | if (curr.data == data) { 129 | this.splay(curr); 130 | return true; 131 | } else if (curr.data > data) { 132 | curr = curr.left; 133 | } else { 134 | curr = curr.right; 135 | } 136 | } 137 | return false; 138 | } 139 | 140 | insert(data) { 141 | let newNode = new Node(data, null, null); 142 | if (this.root == null) { 143 | this.root = newNode; 144 | return; 145 | } 146 | let node = this.root; 147 | let parent = null; 148 | while (node != null) { 149 | parent = node; 150 | if (node.data > data) { 151 | node = node.left; 152 | } else if (node.data < data) { 153 | node = node.right; 154 | } else { 155 | this.splay(node); 156 | // duplicate insertion not allowed but splaying for it. 157 | return; 158 | } 159 | } 160 | newNode.parent = parent; 161 | if (parent.data > data) { 162 | parent.left = newNode; 163 | } else { 164 | parent.right = newNode; 165 | } 166 | this.splay(newNode); 167 | } 168 | 169 | findMinNode(curr) { 170 | let node = curr; 171 | if (node == null) { 172 | return null; 173 | } 174 | while (node.left != null) { 175 | node = node.left; 176 | } 177 | return node; 178 | } 179 | 180 | delete(data) { 181 | let node = this.root; 182 | let parent = null; 183 | let next = null; 184 | while (node != null) { 185 | if (node.data == data) { 186 | parent = node.parent; 187 | if (node.left == null && node.right == null) { 188 | next = null; 189 | } else if (node.left == null) { 190 | next = node.right; 191 | } else if (node.right == null) { 192 | next = node.left; 193 | } 194 | if (node.left == null || node.right == null) { 195 | if (node == this.root) { 196 | this.root = next; 197 | return; 198 | } 199 | if (parent.left == node) { 200 | parent.left = next; 201 | } else { 202 | parent.right = next; 203 | } 204 | if (next != null) { 205 | next.parent = parent; 206 | } 207 | break; 208 | } 209 | let minNode = this.findMinNode(node.right); 210 | data = minNode.data; 211 | node.data = data; 212 | node = node.right; 213 | } else if (node.data > data) { 214 | parent = node; 215 | node = node.left; 216 | } else { 217 | parent = node; 218 | node = node.right; 219 | } 220 | } 221 | this.splay(parent); 222 | } 223 | 224 | printInOrder() { 225 | this.printInOrderUtil(this.root); 226 | console.log(); 227 | } 228 | 229 | printInOrder(node) { 230 | /* In order */ 231 | if (node != null) { 232 | this.printInOrderUtil(node.left); 233 | console.log(node.data + " "); 234 | this.printInOrderUtil(node.right); 235 | } 236 | } 237 | } 238 | 239 | // Testing code. 240 | let tree = new SPLAYTree(); 241 | tree.insert(5); 242 | tree.insert(4); 243 | tree.insert(6); 244 | tree.insert(3); 245 | tree.insert(2); 246 | tree.insert(1); 247 | tree.insert(3); 248 | tree.printTree(); 249 | console.log("Value 2 found: " + tree.find(2)); 250 | tree.delete(2); 251 | tree.delete(5); 252 | tree.printTree(); 253 | 254 | /* 255 | R:3 256 | L:2 257 | | L:1 258 | R:6 259 | L:4 260 | | R:5 261 | 262 | Value 2 found: true 263 | R:4 264 | L:3 265 | | L:1 266 | R:6 267 | */ -------------------------------------------------------------------------------- /Tree/SegmentTree.js: -------------------------------------------------------------------------------- 1 | class SegmentTree 2 | { 3 | constructor(input) { 4 | this.size = input.length; // Height of segment tree. 5 | let x = parseInt(Math.ceil(Math.log(this.size) / Math.log(2))); //Maximum size of segment tree 6 | let max_size = 2 * parseInt(Math.pow(2, x)) - 1; // Allocate memory for segment tree 7 | this.segArr = Array(max_size).fill(0); 8 | this.constructST(input, 0, this.size - 1, 0); 9 | } 10 | 11 | constructST(input, start, end, index) { 12 | // Store it in current node of the segment tree and return 13 | if (start == end) { 14 | this.segArr[index] = input[start]; 15 | return input[start]; 16 | } 17 | // If there are more than one elements, 18 | // then traverse left and right subtrees 19 | // and store the sum of values in current node. 20 | let mid = parseInt((start + end) / 2); 21 | this.segArr[index] = this.constructST(input, start, mid, index * 2 + 1) + this.constructST(input, mid + 1, end, index * 2 + 2); 22 | return this.segArr[index]; 23 | } 24 | 25 | getSum(start, end) { 26 | // Check for error conditions. 27 | if (start > end || start < 0 || end > this.size - 1) { 28 | console.log("Invalid Input."); 29 | return -1; 30 | } 31 | return this.getSumUtil(0, this.size - 1, start, end, 0); 32 | } 33 | 34 | getSumUtil(segStart, segEnd, queryStart, queryEnd, index) { 35 | if (queryStart <= segStart && segEnd <= queryEnd) { 36 | // complete overlapping case. 37 | return this.segArr[index]; 38 | } 39 | if (segEnd < queryStart || queryEnd < segStart) { 40 | // no overlapping case. 41 | return 0; 42 | } 43 | // Segment tree is partly overlaps with the query range. 44 | let mid = parseInt((segStart + segEnd) / 2); 45 | return this.getSumUtil(segStart, mid, queryStart, queryEnd, 2 * index + 1) + this.getSumUtil(mid + 1, segEnd, queryStart, queryEnd, 2 * index + 2); 46 | } 47 | 48 | set(arr, ind, val) { 49 | // Check for error conditions. 50 | if (ind < 0 || ind > this.size - 1) { 51 | console.log("Invalid Input."); 52 | return; 53 | } 54 | arr[ind] = val; 55 | // Set new value in segment tree 56 | this.setUtil(0, this.size - 1, ind, val, 0); 57 | } 58 | 59 | // Always diff will be returned. 60 | setUtil(segStart, segEnd, ind, val, index) { 61 | // set index lies outside the range of current segment. 62 | // So diff to its parent node will be zero. 63 | if (ind < segStart || ind > segEnd) { 64 | return 0; 65 | } 66 | // If the input index is in range of this node, then set the 67 | // value of the node and its children 68 | if (segStart == segEnd) { 69 | if (segStart == ind) { 70 | // Index that need to be set. 71 | let diff = val - this.segArr[index]; 72 | this.segArr[index] = val; 73 | return diff; 74 | } else { 75 | return 0; 76 | } 77 | } 78 | let mid = parseInt((segStart + segEnd) / 2); 79 | let diff = this.setUtil(segStart, mid, ind, val, 2 * index + 1) + this.setUtil(mid + 1, segEnd, ind, val, 2 * index + 2); 80 | // Current node value is set with diff. 81 | this.segArr[index] = this.segArr[index] + diff; 82 | // Value of diff is propagated to the parent node. 83 | return diff; 84 | } 85 | } 86 | 87 | // Testing code. 88 | let arr = [1, 2, 4, 8, 16, 32, 64]; 89 | let tree = new SegmentTree(arr); 90 | console.log("Sum of values in the range(0, 3): " + tree.getSum(1, 3)); 91 | console.log("Sum of values of all the elements: " + tree.getSum(0, arr.length - 1)); 92 | tree.set(arr, 1, 10); 93 | console.log("Sum of values in the range(0, 3): " + tree.getSum(1, 3)); 94 | console.log("Sum of values of all the elements: " + tree.getSum(0, arr.length - 1)); 95 | 96 | /* 97 | Sum of values in the range(0, 3): 14 98 | Sum of values of all the elements: 127 99 | Sum of values in the range(0, 3): 22 100 | Sum of values of all the elements: 135 101 | */ -------------------------------------------------------------------------------- /Tree/rangeMaxST.js: -------------------------------------------------------------------------------- 1 | class rangeMaxST 2 | { 3 | constructor(input) { 4 | this.n = input.length; // Height of segment tree. 5 | let x = parseInt(Math.ceil(Math.log(this.n) / Math.log(2))); //Maximum size of segment tree 6 | let max_size = 2 * parseInt(Math.pow(2, x)) - 1; // Allocate memory for segment tree 7 | this.segArr = Array(max_size).fill(0); 8 | this.constructST(input, 0, this.n - 1, 0); 9 | } 10 | 11 | constructST(input, start, end, index) { 12 | // Store it in current node of the segment tree and return 13 | if (start == end) { 14 | this.segArr[index] = input[start]; 15 | return input[start]; 16 | } 17 | // If there are more than one elements, then traverse left and right subtrees 18 | // and store the minimum of values in current node. 19 | let mid = parseInt((start + end) / 2); 20 | this.segArr[index] = Math.max(this.constructST(input, start, mid, index * 2 + 1), 21 | this.constructST(input, mid + 1, end, index * 2 + 2)); 22 | return this.segArr[index]; 23 | } 24 | 25 | getMax(start, end) { 26 | // Check for error conditions. 27 | if (start > end || start < 0 || end > this.n - 1) { 28 | console.log("Invalid Input."); 29 | return Number.MIN_VALUE; 30 | } 31 | return this.getMaxUtil(0, this.n - 1, start, end, 0); 32 | } 33 | 34 | getMaxUtil(segStart, segEnd, queryStart, queryEnd, index) { 35 | if (queryStart <= segStart && segEnd <= queryEnd) { 36 | // complete overlapping case. 37 | return this.segArr[index]; 38 | } 39 | if (segEnd < queryStart || queryEnd < segStart) { 40 | // no overlapping case. 41 | return Number.MIN_VALUE; 42 | } 43 | // Segment tree is partly overlaps with the query range. 44 | let mid = parseInt((segStart + segEnd) / 2); 45 | return Math.max(this.getMaxUtil(segStart, mid, queryStart, queryEnd, 2 * index + 1), 46 | this.getMaxUtil(mid + 1, segEnd, queryStart, queryEnd, 2 * index + 2)); 47 | } 48 | 49 | update(ind, val) { 50 | // Check for error conditions. 51 | if (ind < 0 || ind > this.n - 1) { 52 | console.log("Invalid Input."); 53 | return; 54 | } 55 | // Update the values in segment tree 56 | this.updateUtil(0, this.n - 1, ind, val, 0); 57 | } 58 | 59 | // Always min inside valid range will be returned. 60 | updateUtil(segStart, segEnd, ind, val, index) { 61 | // Update index lies outside the range of current segment. 62 | // So minimum will not change. 63 | if (ind < segStart || ind > segEnd) { 64 | return this.segArr[index]; 65 | } 66 | // If the input index is in range of this node, then update the 67 | // value of the node and its children 68 | if (segStart == segEnd) { 69 | if (segStart == ind) { 70 | // Index value need to be updated. 71 | this.segArr[index] = val; 72 | return val; 73 | } else { 74 | return this.segArr[index]; 75 | } 76 | } 77 | let mid = parseInt((segStart + segEnd) / 2); 78 | // Current node value is updated with min. 79 | this.segArr[index] = Math.max(this.updateUtil(segStart, mid, ind, val, 2 * index + 1), 80 | this.updateUtil(mid + 1, segEnd, ind, val, 2 * index + 2)); 81 | // Value of diff is propagated to the parent node. 82 | return this.segArr[index]; 83 | } 84 | } 85 | 86 | // Testing code. 87 | let arr = [1, 8, 2, 7, 3, 6, 4, 5]; 88 | let tree = new rangeMaxST(arr); 89 | console.log("Max value in the range(1, 5): " + tree.getMax(1, 5)); 90 | console.log("Max value in the range(2, 7): " + tree.getMax(2, 7)); 91 | console.log("Max value of all the elements: " + tree.getMax(0, arr.length - 1)); 92 | tree.update(2, 9); 93 | console.log("Max value in the range(1, 5): " + tree.getMax(1, 5)); 94 | console.log("Max value of all the elements: " + tree.getMax(0, arr.length - 1)); 95 | 96 | /* 97 | Max value in the range(1, 5): 8 98 | Max value in the range(2, 7): 7 99 | Max value of all the elements: 8 100 | Max value in the range(1, 5): 9 101 | Max value of all the elements: 9 102 | */ -------------------------------------------------------------------------------- /Tree/rmqST.js: -------------------------------------------------------------------------------- 1 | class rmqST 2 | { 3 | constructor(input) { 4 | this.n = input.length; // Height of segment tree. 5 | let x = parseInt(Math.ceil(Math.log(this.n) / Math.log(2))); //Maximum size of segment tree 6 | let maxSize = 2 * parseInt(Math.pow(2, x)) - 1; // Allocate memory for segment tree 7 | this.segArr = Array(maxSize).fill(0); 8 | this.constructST(input, 0, this.n - 1, 0); 9 | } 10 | 11 | constructST(input, start, end, index) { 12 | // Store it in current node of the segment tree and return 13 | if (start == end) { 14 | this.segArr[index] = input[start]; 15 | return input[start]; 16 | } 17 | // If there are more than one elements, 18 | // then traverse left and right subtrees 19 | // and store the minimum of values in current node. 20 | let mid = parseInt((start + end) / 2); 21 | this.segArr[index] = Math.min(this.constructST(input, start, mid, index * 2 + 1), this.constructST(input, mid + 1, end, index * 2 + 2)); 22 | return this.segArr[index]; 23 | } 24 | 25 | 26 | getMin(start, end) { 27 | // Check for error conditions. 28 | if (start > end || start < 0 || end > this.n - 1) { 29 | console.log("Invalid Input."); 30 | return Number.MAX_VALUE; 31 | } 32 | return this.getMinUtil(0, this.n - 1, start, end, 0); 33 | } 34 | 35 | getMinUtil(segStart, segEnd, queryStart, queryEnd, index) { 36 | if (queryStart <= segStart && segEnd <= queryEnd) { 37 | // complete overlapping case. 38 | return this.segArr[index]; 39 | } 40 | if (segEnd < queryStart || queryEnd < segStart) { 41 | // no overlapping case. 42 | return Number.MAX_VALUE; 43 | } 44 | // Segment tree is partly overlaps with the query range. 45 | let mid = parseInt((segStart + segEnd) / 2); 46 | return Math.min(this.getMinUtil(segStart, mid, queryStart, queryEnd, 2 * index + 1), this.getMinUtil(mid + 1, segEnd, queryStart, queryEnd, 2 * index + 2)); 47 | } 48 | 49 | update(ind, val) { 50 | // Check for error conditions. 51 | if (ind < 0 || ind > this.n - 1) { 52 | console.log("Invalid Input."); 53 | return; 54 | } 55 | // Update the values in segment tree 56 | this.updateUtil(0, this.n - 1, ind, val, 0); 57 | } 58 | 59 | // Always min inside valid range will be returned. 60 | updateUtil(segStart, segEnd, ind, val, index) { 61 | // Update index lies outside the range of current segment. 62 | // So minimum will not change. 63 | if (ind < segStart || ind > segEnd) { 64 | return this.segArr[index]; 65 | } 66 | // If the input index is in range of this node, then update the 67 | // value of the node and its children 68 | if (segStart == segEnd) { 69 | if (segStart == ind) { 70 | // Index value need to be updated. 71 | this.segArr[index] = val; 72 | return val; 73 | } else { 74 | return this.segArr[index]; 75 | } 76 | } 77 | let mid = parseInt((segStart + segEnd) / 2); 78 | // Current node value is updated with min. 79 | this.segArr[index] = Math.min(this.updateUtil(segStart, mid, ind, val, 2 * index + 1), this.updateUtil(mid + 1, segEnd, ind, val, 2 * index + 2)); 80 | // Value of diff is propagated to the parent node. 81 | return this.segArr[index]; 82 | } 83 | } 84 | 85 | // Testing code. 86 | let arr = [2, 3, 1, 7, 12, 5]; 87 | let tree = new rmqST(arr); 88 | console.log("Min value in the range(1, 5): " + tree.getMin(1, 5)); 89 | console.log("Min value of all the elements: " + tree.getMin(0, arr.length - 1)); 90 | tree.update(2, -1); 91 | console.log("Min value in the range(1, 5): " + tree.getMin(1, 5)); 92 | console.log("Min value of all the elements: " + tree.getMin(0, arr.length - 1)); 93 | tree.update(5, -2); 94 | console.log("Min value in the range(0, 4): " + tree.getMin(0, 4)); 95 | console.log("Min value of all the elements: " + tree.getMin(0, arr.length - 1)); 96 | 97 | /* 98 | Min value in the range(1, 5): 1 99 | Min value of all the elements: 1 100 | Min value in the range(1, 5): -1 101 | Min value of all the elements: -1 102 | Min value in the range(0, 4): -1 103 | Min value of all the elements: -2 104 | */ -------------------------------------------------------------------------------- /how to use this book.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hemant-Jain-Author/Data-Structures-and-Algorithms-using-JavaScript/61e28a847e23e74bc987f6882fbb79107664abcc/how to use this book.pdf --------------------------------------------------------------------------------