diff --git a/Week-12/DP1/coin.js b/Week-12/DP1/coin.js new file mode 100644 index 0000000..ccace08 --- /dev/null +++ b/Week-12/DP1/coin.js @@ -0,0 +1,25 @@ +function minCoins(coins, amount) { + // Initialize an array to store the minimum number of coins for each amount + const dp = new Array(amount + 1).fill(Infinity); + + // The minimum number of coins needed to make change for 0 is 0 + dp[0] = 0; + + // Iterate through each coin denomination + for (const coin of coins) { + // Update dp array for each amount from coin to amount + for (let i = coin; i <= amount; i++) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + + // If dp[amount] is still Infinity, it means it's not possible to make the change + return dp[amount] === Infinity ? -1 : dp[amount]; + } + + // Example usage: + const coinDenominations = [1, 2, 5]; + const targetAmount = 11; + + const result = minCoins(coinDenominations, targetAmount); + console.log(result); // Should print 3 (2 coins of 5 and 1 coin of 1 to make 11) \ No newline at end of file diff --git a/Week-12/DP1/eggDrop.js b/Week-12/DP1/eggDrop.js new file mode 100644 index 0000000..f1ff79d --- /dev/null +++ b/Week-12/DP1/eggDrop.js @@ -0,0 +1,39 @@ +function eggDrop(eggs, floors) { + // Create a 2D DP array + const dp = new Array(eggs + 1).fill(null).map(() => new Array(floors + 1).fill(0)); + + // Initialize the base cases + for (let i = 0; i <= eggs; i++) { + dp[i][0] = 0; // Zero attempts needed for 0 floors + dp[i][1] = 1; // One attempt needed for 1 floor + } + + for (let j = 1; j <= floors; j++) { + dp[1][j] = j; // If we have one egg, we need j attempts for j floors + } + + // Fill the DP table for the remaining cases + for (let i = 2; i <= eggs; i++) { + for (let j = 2; j <= floors; j++) { + dp[i][j] = Infinity; + + for (let x = 1; x <= j; x++) { + const maxAttempts = 1 + Math.max(dp[i - 1][x - 1], dp[i][j - x]); + + if (maxAttempts < dp[i][j]) { + dp[i][j] = maxAttempts; + } + } + } + } + + // The minimum number of attempts is stored in dp[eggs][floors] + return dp[eggs][floors]; + } + + // Example usage: + const eggs = 2; + const floors = 100; + + const result = eggDrop(eggs, floors); + console.log(`Minimum attempts needed: ${result}`); \ No newline at end of file diff --git a/Week-12/DP1/fibonacci.js b/Week-12/DP1/fibonacci.js new file mode 100644 index 0000000..f72e58e --- /dev/null +++ b/Week-12/DP1/fibonacci.js @@ -0,0 +1,20 @@ +function calculateFibonacci(n) { + if (n <= 1) { + return n; + } + + const fib = new Array(n + 1); + fib[0] = 0; + fib[1] = 1; + + for (let i = 2; i <= n; i++) { + fib[i] = fib[i - 1] + fib[i - 2]; + } + + return fib[n]; + } + + // Example usage: + const n = 10; + const result = calculateFibonacci(n); + console.log(`The ${n}th Fibonacci number is ${result}`); \ No newline at end of file diff --git a/Week-12/DP1/partition.js b/Week-12/DP1/partition.js new file mode 100644 index 0000000..239a5e0 --- /dev/null +++ b/Week-12/DP1/partition.js @@ -0,0 +1,26 @@ +function canPartition(nums) { + const sum = nums.reduce((acc, num) => acc + num, 0); + + // If the sum is odd, it cannot be partitioned into two equal subsets + if (sum % 2 !== 0) { + return false; + } + + const targetSum = sum / 2; + const dp = new Array(targetSum + 1).fill(false); + dp[0] = true; + + for (const num of nums) { + for (let i = targetSum; i >= num; i--) { + dp[i] = dp[i] || dp[i - num]; + } + } + + return dp[targetSum]; + } + + // Example usage: + const nums = [1, 5, 11, 5]; + + const result = canPartition(nums); + console.log(result); // Should print true (subset [1, 5, 5] and subset [11] have equal sums) \ No newline at end of file diff --git a/Week-12/DP1/wordBreak.js b/Week-12/DP1/wordBreak.js new file mode 100644 index 0000000..d36431f --- /dev/null +++ b/Week-12/DP1/wordBreak.js @@ -0,0 +1,24 @@ +function wordBreak(s, wordDict) { + const wordSet = new Set(wordDict); + const n = s.length; + const dp = new Array(n + 1).fill(false); + dp[0] = true; + + for (let i = 1; i <= n; i++) { + for (let j = 0; j < i; j++) { + if (dp[j] && wordSet.has(s.substring(j, i))) { + dp[i] = true; + break; + } + } + } + + return dp[n]; + } + + // Example usage: + const s = "leetcode"; + const wordDict = ["leet", "code"]; + + const result = wordBreak(s, wordDict); + console.log(result); // Should print true (can be segmented into "leet" and "code") \ No newline at end of file diff --git a/Week-12/Heaps1/checkMinHeap.js b/Week-12/Heaps1/checkMinHeap.js new file mode 100644 index 0000000..08abfbc --- /dev/null +++ b/Week-12/Heaps1/checkMinHeap.js @@ -0,0 +1,29 @@ +function isMinHeap(arr) { + const n = arr.length; + + // Check the min heap property for each node + for (let i = 0; i < n; i++) { + // Calculate the indices of the left and right children + const leftChildIndex = 2 * i + 1; + const rightChildIndex = 2 * i + 2; + + // Check if the left child exists and if it violates the min heap property + if (leftChildIndex < n && arr[i] > arr[leftChildIndex]) { + return false; + } + + // Check if the right child exists and if it violates the min heap property + if (rightChildIndex < n && arr[i] > arr[rightChildIndex]) { + return false; + } + } + + return true; // All nodes satisfy the min heap property + } + + // Example usage: + const minHeapArray = [3, 5, 7, 9, 11, 13]; + const notMinHeapArray = [3, 7, 5, 9, 11, 13]; + + console.log(isMinHeap(minHeapArray)); // Should print true + console.log(isMinHeap(notMinHeapArray)); // Should print false \ No newline at end of file diff --git a/Week-12/Heaps1/kthLargest.js b/Week-12/Heaps1/kthLargest.js new file mode 100644 index 0000000..00dda1a --- /dev/null +++ b/Week-12/Heaps1/kthLargest.js @@ -0,0 +1,91 @@ +class MaxHeap { + constructor() { + this.heap = []; + } + + push(val) { + this.heap.push(val); + this.heapifyUp(); + } + + pop() { + if (this.isEmpty()) { + return null; + } + if (this.heap.length === 1) { + return this.heap.pop(); + } + + const root = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.heapifyDown(); + return root; + } + + isEmpty() { + return this.heap.length === 0; + } + + heapifyUp() { + let currentIndex = this.heap.length - 1; + let parentIndex; + + while (currentIndex > 0) { + parentIndex = Math.floor((currentIndex - 1) / 2); + + if (this.heap[currentIndex] <= this.heap[parentIndex]) { + break; + } + + [this.heap[currentIndex], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[currentIndex]]; + currentIndex = parentIndex; + } + } + + heapifyDown() { + let currentIndex = 0; + let leftChildIndex, rightChildIndex, largestChildIndex; + + while (currentIndex < this.heap.length) { + leftChildIndex = 2 * currentIndex + 1; + rightChildIndex = 2 * currentIndex + 2; + largestChildIndex = currentIndex; + + if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] > this.heap[largestChildIndex]) { + largestChildIndex = leftChildIndex; + } + + if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] > this.heap[largestChildIndex]) { + largestChildIndex = rightChildIndex; + } + + if (largestChildIndex === currentIndex) { + break; + } + + [this.heap[currentIndex], this.heap[largestChildIndex]] = [this.heap[largestChildIndex], this.heap[currentIndex]]; + currentIndex = largestChildIndex; + } + } + } + + function findKthLargest(nums, k) { + const maxHeap = new MaxHeap(); + + for (const num of nums) { + maxHeap.push(num); + + if (maxHeap.heap.length > k) { + maxHeap.pop(); + } + } + + return maxHeap.pop(); + } + + // Example usage: + const unsortedArray = [3, 1, 4, 1, 5, 9, 2, 6, 5]; + const k = 4; + + const kthLargest = findKthLargest(unsortedArray, k); + console.log(`The ${k}th largest element is:`, kthLargest); \ No newline at end of file diff --git a/Week-12/Heaps1/kthSmallest.js b/Week-12/Heaps1/kthSmallest.js new file mode 100644 index 0000000..36a98e9 --- /dev/null +++ b/Week-12/Heaps1/kthSmallest.js @@ -0,0 +1,107 @@ +class MinHeap { + constructor() { + this.heap = []; + } + + push(val, row, col) { + this.heap.push({ val, row, col }); + this.heapifyUp(); + } + + pop() { + if (this.isEmpty()) { + return null; + } + if (this.heap.length === 1) { + return this.heap.pop(); + } + + const root = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.heapifyDown(); + return root; + } + + isEmpty() { + return this.heap.length === 0; + } + + heapifyUp() { + let currentIndex = this.heap.length - 1; + let parentIndex; + + while (currentIndex > 0) { + parentIndex = Math.floor((currentIndex - 1) / 2); + + if (this.heap[currentIndex].val >= this.heap[parentIndex].val) { + break; + } + + [this.heap[currentIndex], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[currentIndex]]; + currentIndex = parentIndex; + } + } + + heapifyDown() { + let currentIndex = 0; + let leftChildIndex, rightChildIndex, smallestChildIndex; + + while (currentIndex < this.heap.length) { + leftChildIndex = 2 * currentIndex + 1; + rightChildIndex = 2 * currentIndex + 2; + smallestChildIndex = currentIndex; + + if (leftChildIndex < this.heap.length && this.heap[leftChildIndex].val < this.heap[smallestChildIndex].val) { + smallestChildIndex = leftChildIndex; + } + + if (rightChildIndex < this.heap.length && this.heap[rightChildIndex].val < this.heap[smallestChildIndex].val) { + smallestChildIndex = rightChildIndex; + } + + if (smallestChildIndex === currentIndex) { + break; + } + + [this.heap[currentIndex], this.heap[smallestChildIndex]] = [this.heap[smallestChildIndex], this.heap[currentIndex]]; + currentIndex = smallestChildIndex; + } + } + } + + function findKthSmallest(matrix, k) { + const minHeap = new MinHeap(); + + const rows = matrix.length; + const cols = matrix[0].length; + + // Add the first element (top-left) to the min-heap + minHeap.push(matrix[0][0], 0, 0); + + for (let i = 0; i < k - 1; i++) { + const { val, row, col } = minHeap.pop(); + + // If the current element is not in the last column, push the element from the same row to the right + if (col < cols - 1) { + minHeap.push(matrix[row][col + 1], row, col + 1); + } + + // If the current element is not in the last row, push the element from the same column below + if (row < rows - 1) { + minHeap.push(matrix[row + 1][col], row + 1, col); + } + } + + return minHeap.pop().val; + } + + // Example usage: + const matrix = [ + [1, 3, 5], + [2, 4, 8], + [6, 7, 9] + ]; + const k = 3; + + const kthSmallest = findKthSmallest(matrix, k); + console.log(`The ${k}th smallest element is:`, kthSmallest); \ No newline at end of file diff --git a/Week-12/Heaps1/merge.js b/Week-12/Heaps1/merge.js new file mode 100644 index 0000000..6219f98 --- /dev/null +++ b/Week-12/Heaps1/merge.js @@ -0,0 +1,101 @@ +class MinHeap { + constructor() { + this.heap = []; + } + + push(val, arrayIndex) { + this.heap.push({ val, arrayIndex }); + this.bubbleUp(); + } + + pop() { + if (this.isEmpty()) return null; + if (this.heap.length === 1) return this.heap.pop(); + + const root = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.bubbleDown(); + return root; + } + + isEmpty() { + return this.heap.length === 0; + } + + bubbleUp() { + let currentIdx = this.heap.length - 1; + while (currentIdx > 0) { + const parentIdx = Math.floor((currentIdx - 1) / 2); + if (this.heap[currentIdx].val < this.heap[parentIdx].val) { + [this.heap[currentIdx], this.heap[parentIdx]] = [this.heap[parentIdx], this.heap[currentIdx]]; + currentIdx = parentIdx; + } else { + break; + } + } + } + + bubbleDown() { + let currentIdx = 0; + while (currentIdx < this.heap.length) { + const leftIdx = 2 * currentIdx + 1; + const rightIdx = 2 * currentIdx + 2; + let smallestIdx = currentIdx; + + if (leftIdx < this.heap.length && this.heap[leftIdx].val < this.heap[smallestIdx].val) { + smallestIdx = leftIdx; + } + + if (rightIdx < this.heap.length && this.heap[rightIdx].val < this.heap[smallestIdx].val) { + smallestIdx = rightIdx; + } + + if (smallestIdx === currentIdx) { + break; + } + + [this.heap[currentIdx], this.heap[smallestIdx]] = [this.heap[smallestIdx], this.heap[currentIdx]]; + currentIdx = smallestIdx; + } + } + } + + function mergeSortedArrays(arrays) { + const k = arrays.length; + const minHeap = new MinHeap(); + + // Initialize the min-heap with the first element from each array + for (let i = 0; i < k; i++) { + if (arrays[i].length > 0) { + minHeap.push(arrays[i][0], i); + } + } + + const mergedArray = []; + + while (!minHeap.isEmpty()) { + const { val, arrayIndex } = minHeap.pop(); + mergedArray.push(val); + + // Add the next element from the same array to the min-heap + if (arrays[arrayIndex].length > 1) { + minHeap.push(arrays[arrayIndex][1], arrayIndex); + arrays[arrayIndex].shift(); // Remove the processed element + } + } + + return mergedArray; + } + + // Example usage: + const k = parseInt(prompt("Enter the number of sorted arrays:")); + const arrays = []; + + for (let i = 0; i < k; i++) { + const input = prompt(`Enter elements for array ${i + 1} (comma-separated):`); + const array = input.split(",").map(Number); + arrays.push(array); + } + + const mergedArray = mergeSortedArrays(arrays); + console.log("Merged and sorted array:", mergedArray); \ No newline at end of file diff --git a/Week-12/Heaps1/minElement.js b/Week-12/Heaps1/minElement.js new file mode 100644 index 0000000..a14d546 --- /dev/null +++ b/Week-12/Heaps1/minElement.js @@ -0,0 +1,12 @@ +function findMinElement(heap) { + if (heap.length === 0) { + throw new Error("The heap is empty."); + } + + return heap[0]; + } + + // Example usage: + const minHeap = [2, 4, 7, 9, 10, 15]; + const minElement = findMinElement(minHeap); + console.log("Minimum element in the min heap:", minElement); \ No newline at end of file diff --git a/Week-12/Heaps2/kCLosest.js b/Week-12/Heaps2/kCLosest.js new file mode 100644 index 0000000..aa9f966 --- /dev/null +++ b/Week-12/Heaps2/kCLosest.js @@ -0,0 +1,106 @@ +class MaxHeap { + constructor() { + this.heap = []; + } + + push(point) { + this.heap.push(point); + this.heapifyUp(); + } + + pop() { + if (this.isEmpty()) { + return null; + } + if (this.heap.length === 1) { + return this.heap.pop(); + } + + const root = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.heapifyDown(); + return root; + } + + isEmpty() { + return this.heap.length === 0; + } + + heapifyUp() { + let currentIndex = this.heap.length - 1; + let parentIndex; + + while (currentIndex > 0) { + parentIndex = Math.floor((currentIndex - 1) / 2); + + if (this.distance(this.heap[currentIndex]) <= this.distance(this.heap[parentIndex])) { + break; + } + + [this.heap[currentIndex], this.heap[parentIndex]] = [this.heap[parentIndex], this.heap[currentIndex]]; + currentIndex = parentIndex; + } + } + + heapifyDown() { + let currentIndex = 0; + let leftChildIndex, rightChildIndex, largestChildIndex; + + while (currentIndex < this.heap.length) { + leftChildIndex = 2 * currentIndex + 1; + rightChildIndex = 2 * currentIndex + 2; + largestChildIndex = currentIndex; + + if (leftChildIndex < this.heap.length && this.distance(this.heap[leftChildIndex]) > this.distance(this.heap[largestChildIndex])) { + largestChildIndex = leftChildIndex; + } + + if (rightChildIndex < this.heap.length && this.distance(this.heap[rightChildIndex]) > this.distance(this.heap[largestChildIndex])) { + largestChildIndex = rightChildIndex; + } + + if (largestChildIndex === currentIndex) { + break; + } + + [this.heap[currentIndex], this.heap[largestChildIndex]] = [this.heap[largestChildIndex], this.heap[currentIndex]]; + currentIndex = largestChildIndex; + } + } + + distance(point) { + return Math.sqrt(point[0] ** 2 + point[1] ** 2); + } + } + + function findClosestPointsToOrigin(points, k) { + const maxHeap = new MaxHeap(); + + for (const point of points) { + maxHeap.push(point); + + if (maxHeap.heap.length > k) { + maxHeap.pop(); + } + } + + const closestPoints = []; + + while (!maxHeap.isEmpty()) { + closestPoints.push(maxHeap.pop()); + } + + return closestPoints.reverse(); + } + + // Example usage: + const k = parseInt(prompt("Enter the value of k:")); + const pointsInput = prompt("Enter points (x,y) separated by spaces:"); + + const points = pointsInput.split(" ").map(pointStr => { + const [x, y] = pointStr.split(",").map(Number); + return [x, y]; + }); + + const closestPoints = findClosestPointsToOrigin(points, k); + console.log(`The ${k} closest points to the origin are:`, closestPoints); \ No newline at end of file diff --git a/Week-12/Heaps2/median.js b/Week-12/Heaps2/median.js new file mode 100644 index 0000000..aecd75b --- /dev/null +++ b/Week-12/Heaps2/median.js @@ -0,0 +1,117 @@ +class Heap { + constructor(compare) { + this.heap = []; + this.compare = compare; + } + + size() { + return this.heap.length; + } + + isEmpty() { + return this.size() === 0; + } + + insert(val) { + this.heap.push(val); + this.heapifyUp(); + } + + extract() { + if (this.isEmpty()) return null; + if (this.size() === 1) return this.heap.pop(); + + const root = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.heapifyDown(); + return root; + } + + peek() { + return this.isEmpty() ? null : this.heap[0]; + } + + heapifyUp() { + let currentIdx = this.size() - 1; + while (currentIdx > 0) { + const parentIdx = Math.floor((currentIdx - 1) / 2); + if (this.compare(this.heap[currentIdx], this.heap[parentIdx]) < 0) { + this.swap(currentIdx, parentIdx); + currentIdx = parentIdx; + } else { + break; + } + } + } + + heapifyDown() { + let currentIdx = 0; + while (true) { + const leftChildIdx = 2 * currentIdx + 1; + const rightChildIdx = 2 * currentIdx + 2; + let smallestChildIdx = currentIdx; + + if ( + leftChildIdx < this.size() && + this.compare(this.heap[leftChildIdx], this.heap[smallestChildIdx]) < 0 + ) { + smallestChildIdx = leftChildIdx; + } + + if ( + rightChildIdx < this.size() && + this.compare(this.heap[rightChildIdx], this.heap[smallestChildIdx]) < 0 + ) { + smallestChildIdx = rightChildIdx; + } + + if (currentIdx === smallestChildIdx) break; + + this.swap(currentIdx, smallestChildIdx); + currentIdx = smallestChildIdx; + } + } + + swap(i, j) { + [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; + } + } + + function calculateMedian(stream) { + const maxHeap = new Heap((a, b) => b - a); + const minHeap = new Heap((a, b) => a - b); + + const medianValues = []; + + for (const num of stream) { + if (maxHeap.isEmpty() || num < maxHeap.peek()) { + maxHeap.insert(num); + } else { + minHeap.insert(num); + } + + // Balance the heaps + if (maxHeap.size() > minHeap.size() + 1) { + minHeap.insert(maxHeap.extract()); + } else if (minHeap.size() > maxHeap.size()) { + maxHeap.insert(minHeap.extract()); + } + + // Calculate median + if (maxHeap.size() === minHeap.size()) { + const median = (maxHeap.peek() + minHeap.peek()) / 2; + medianValues.push(median); + } else { + medianValues.push(maxHeap.peek()); + } + } + + return medianValues; + } + + // Input + const input = prompt("Enter a stream of integers separated by spaces: "); + const stream = input.split(" ").map(Number); + + const medians = calculateMedian(stream); + console.log("Medians of the stream: ", medians); \ No newline at end of file diff --git a/Week-12/Heaps2/minHeap.js b/Week-12/Heaps2/minHeap.js new file mode 100644 index 0000000..a8ad2a0 --- /dev/null +++ b/Week-12/Heaps2/minHeap.js @@ -0,0 +1,79 @@ +class TreeNode { + constructor(val) { + this.val = val; + this.left = this.right = null; + } + } + + function inOrderTraversal(root, values) { + if (root === null) { + values.push(-1); // Represent null nodes with -1 + return; + } + inOrderTraversal(root.left, values); + values.push(root.val); + inOrderTraversal(root.right, values); + } + + function sortedArrayToMinHeap(sortedArray) { + if (sortedArray.length === 0) { + return null; + } + + const mid = Math.floor(sortedArray.length / 2); + const root = new TreeNode(sortedArray[mid]); + + root.left = sortedArrayToMinHeap(sortedArray.slice(0, mid)); + root.right = sortedArrayToMinHeap(sortedArray.slice(mid + 1)); + + return root; + } + + function binaryTreeToMinHeap(root) { + const values = []; + inOrderTraversal(root, values); + + // Filter out the -1 (null) values + const sortedArray = values.filter(val => val !== -1).sort((a, b) => a - b); + + return sortedArrayToMinHeap(sortedArray); + } + + // Helper function to print the binary tree in level order (for testing) + function levelOrderTraversal(root) { + const result = []; + const queue = []; + + if (root !== null) { + queue.push(root); + } + + while (queue.length > 0) { + const node = queue.shift(); + result.push(node.val); + + if (node.left !== null) { + queue.push(node.left); + } + + if (node.right !== null) { + queue.push(node.right); + } + } + + return result; + } + + // Example usage: + const binaryTree = new TreeNode(4); + binaryTree.left = new TreeNode(2); + binaryTree.right = new TreeNode(6); + binaryTree.left.left = new TreeNode(1); + binaryTree.left.right = new TreeNode(3); + binaryTree.right.left = new TreeNode(5); + binaryTree.right.right = new TreeNode(7); + + console.log("Original Binary Tree (in-order traversal):", levelOrderTraversal(binaryTree)); + + const minHeapTree = binaryTreeToMinHeap(binaryTree); + console.log("Min Heap Binary Tree (level order traversal):", levelOrderTraversal(minHeapTree)); \ No newline at end of file diff --git a/Week-12/Heaps2/smallest.js b/Week-12/Heaps2/smallest.js new file mode 100644 index 0000000..bcd23af --- /dev/null +++ b/Week-12/Heaps2/smallest.js @@ -0,0 +1,132 @@ +class MinHeap { + constructor() { + this.heap = []; + } + + push(value, listIndex) { + this.heap.push({ value, listIndex }); + this.heapifyUp(); + } + + pop() { + if (this.isEmpty()) { + return null; + } + const minValue = this.heap[0]; + const lastValue = this.heap.pop(); + if (!this.isEmpty()) { + this.heap[0] = lastValue; + this.heapifyDown(); + } + return minValue; + } + + isEmpty() { + return this.heap.length === 0; + } + + heapifyUp() { + let currentIndex = this.heap.length - 1; + while (currentIndex > 0) { + const parentIndex = Math.floor((currentIndex - 1) / 2); + if (this.heap[currentIndex].value < this.heap[parentIndex].value) { + this.swap(currentIndex, parentIndex); + currentIndex = parentIndex; + } else { + break; + } + } + } + + heapifyDown() { + let currentIndex = 0; + const length = this.heap.length; + + while (true) { + const leftChildIndex = 2 * currentIndex + 1; + const rightChildIndex = 2 * currentIndex + 2; + let smallestChildIndex = currentIndex; + + if ( + leftChildIndex < length && + this.heap[leftChildIndex].value < this.heap[smallestChildIndex].value + ) { + smallestChildIndex = leftChildIndex; + } + + if ( + rightChildIndex < length && + this.heap[rightChildIndex].value < this.heap[smallestChildIndex].value + ) { + smallestChildIndex = rightChildIndex; + } + + if (currentIndex === smallestChildIndex) { + break; + } + + this.swap(currentIndex, smallestChildIndex); + currentIndex = smallestChildIndex; + } + } + + swap(i, j) { + [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; + } + } + + function findSmallestRange(kSortedLists) { + const minHeap = new MinHeap(); + let maxValue = Number.NEGATIVE_INFINITY; + let minRange = Number.POSITIVE_INFINITY; + let rangeStart, rangeEnd; + + // Initialize the min-heap with the first element from each list + for (let i = 0; i < kSortedLists.length; i++) { + const list = kSortedLists[i]; + if (list.length === 0) { + // If any list is empty, we can't cover all lists, so return immediately + return null; + } + const value = list[0]; + minHeap.push(value, i); + maxValue = Math.max(maxValue, value); + } + + while (true) { + const { value, listIndex } = minHeap.pop(); + const list = kSortedLists[listIndex]; + const nextIndex = 1; + + if (nextIndex >= list.length) { + // If any list is exhausted, break the loop + break; + } + + const nextValue = list[nextIndex]; + minHeap.push(nextValue, listIndex); + maxValue = Math.max(maxValue, nextValue); + + // Calculate the current range + const currentRange = maxValue - minHeap.heap[0].value; + + if (currentRange < minRange) { + minRange = currentRange; + rangeStart = minHeap.heap[0].value; + rangeEnd = maxValue; + } + } + + return [rangeStart, rangeEnd]; + } + + // Example usage: + const kSortedLists = [ + [4, 10, 15, 24, 26], + [0, 9, 12, 20], + [5, 18, 22, 30], + ]; + + const [smallestRangeStart, smallestRangeEnd] = findSmallestRange(kSortedLists); + + console.log(`Smallest Range: [${smallestRangeStart}, ${smallestRangeEnd}]`); \ No newline at end of file diff --git a/Week-12/Heaps2/sort.js b/Week-12/Heaps2/sort.js new file mode 100644 index 0000000..cd23db3 --- /dev/null +++ b/Week-12/Heaps2/sort.js @@ -0,0 +1,100 @@ +class MinHeap { + constructor() { + this.heap = []; + } + + push(value) { + this.heap.push(value); + this.heapifyUp(); + } + + pop() { + if (this.isEmpty()) { + return null; + } + const minValue = this.heap[0]; + const lastValue = this.heap.pop(); + if (!this.isEmpty()) { + this.heap[0] = lastValue; + this.heapifyDown(); + } + return minValue; + } + + isEmpty() { + return this.heap.length === 0; + } + + heapifyUp() { + let currentIndex = this.heap.length - 1; + while (currentIndex > 0) { + const parentIndex = Math.floor((currentIndex - 1) / 2); + if (this.heap[currentIndex] < this.heap[parentIndex]) { + this.swap(currentIndex, parentIndex); + currentIndex = parentIndex; + } else { + break; + } + } + } + + heapifyDown() { + let currentIndex = 0; + const length = this.heap.length; + + while (true) { + const leftChildIndex = 2 * currentIndex + 1; + const rightChildIndex = 2 * currentIndex + 2; + let smallestChildIndex = currentIndex; + + if ( + leftChildIndex < length && + this.heap[leftChildIndex] < this.heap[smallestChildIndex] + ) { + smallestChildIndex = leftChildIndex; + } + + if ( + rightChildIndex < length && + this.heap[rightChildIndex] < this.heap[smallestChildIndex] + ) { + smallestChildIndex = rightChildIndex; + } + + if (currentIndex === smallestChildIndex) { + break; + } + + this.swap(currentIndex, smallestChildIndex); + currentIndex = smallestChildIndex; + } + } + + swap(i, j) { + [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; + } + } + + function heapSort(arr) { + const minHeap = new MinHeap(); + const sortedArray = []; + + // Build the min-heap + for (const num of arr) { + minHeap.push(num); + } + + // Extract the minimum elements and add them to the sorted array + while (!minHeap.isEmpty()) { + const minValue = minHeap.pop(); + sortedArray.push(minValue); + } + + return sortedArray; + } + + // Example usage: + const unsortedArray = [9, -2, 6, 0, 4, 3, -7, 8]; + const sortedArray = heapSort(unsortedArray); + + console.log("Sorted Array:", sortedArray); \ No newline at end of file