diff --git a/LeetcodeProblems/Algorithms/easy/Best_Time_to_buy_and_sell_stock.js b/LeetcodeProblems/Algorithms/easy/Best_Time_to_buy_and_sell_stock.js new file mode 100644 index 0000000..a94d16b --- /dev/null +++ b/LeetcodeProblems/Algorithms/easy/Best_Time_to_buy_and_sell_stock.js @@ -0,0 +1,95 @@ +/* +121. Best Time to Buy and Sell Stock +https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ + +Problem: +You are given an array prices where prices[i] is the price of a given stock on the ith day. + +You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. + +Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0. + + + +Example 1: + +Input: prices = [7,1,5,3,6,4] +Output: 5 +Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. +Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell. +Example 2: + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: In this case, no transactions are done and the max profit = 0. + +Constraints: + +1 <= prices.length <= 10^5 +0 <= prices[i] <= 10^4 +*/ +/* +Approach: +We will use a Two pointers strategy (Left and Right pointers). +The first will start pointing to the first element, and the right to the second position of array. +The Left is to buy stock and Right is to sell stock + +We initialize our maxProfitValue as 0. + +Now we will start our while loop, and we will run till our +Right pointer less than the array's length. + +For Example: +prices=[7,1,5,3,6,4] +Note: +prices[left] --> buy stock +prices[right] --> sell stock +We will check the price at the right and left pointer + +step 1: + +price[left]=7 price[right]=1 profit=-6 +here, price[left] is greater than price[right], so we will move the left pointer to the right position +and increment our right pointer by 1. We always want our left point to be the minimum. + +step 2: + +price[left]=1 price[right]=5 profit=4 +here, price[left] is less than price[right], which means we will get profit, +so we will update our maxProfitValue and move our right pointer alone + +step 3: + +price[left]=1 price[right]=3 profit=2 +here, price[left] is less than price[right], we will get profit, so we will compare the maxProfitValue with the current profit. +We will update our maxProfitValue and move our right pointer alone + +step 4: + +price[left]=1 price[right]=6 profit=5 +same logic as above + +step 5: + +price[left]=1 price[right]=4 profit=3 +same logic as above +*/ + +const maxProfit = (prices) => { + let left = 0; // Buy + let right = 1; // sell + let maxProfitValue = 0; + while (right < prices.length) { + if (prices[left] < prices[right]) { + let profit = prices[right] - prices[left]; // our current profit + + maxProfitValue = Math.max(maxProfitValue, profit); + } else { + left = right; + } + right++; + } + return maxProfitValue; +}; + +module.exports.maxProfit = maxProfit; diff --git a/LeetcodeProblems/Algorithms/hard/First_Missing_Positive.js b/LeetcodeProblems/Algorithms/hard/First_Missing_Positive.js new file mode 100644 index 0000000..8bb6ed3 --- /dev/null +++ b/LeetcodeProblems/Algorithms/hard/First_Missing_Positive.js @@ -0,0 +1,51 @@ +/* +41. First Missing Positive +https://leetcode.com/problems/first-missing-positive/ +Problem: +Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums. +You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space. +Example 1: +Input: nums = [1,2,0] +Output: 3 +Explanation: The numbers in the range [1,2] are all in the array. +Example 2: +Input: nums = [3,4,-1,1] +Output: 2 +Explanation: 1 is in the array but 2 is missing. +Example 3: +Input: nums = [7,8,9,11,12] +Output: 1 +Explanation: The smallest positive integer 1 is missing. +Constraints: +1 <= nums.length <= 10^5 +-2^31 <= nums[i] <= 2^31 - 1 +Explanation +Initialize n +const n = nums.length; +This line sets the variable n to the length of the input array nums. It represents the size of the array. +This is the cyclic sort algorithm. It iterates through the array and, in each step, it checks if the current element nums[i] is within the valid range (1 to n) and not in its correct position. If so, it swaps the element with the one at its correct position. +After the cyclic sort, this loop searches for the first element that is out of place. If nums[i] is not equal to i + 1, it means that i + 1 is the smallest missing positive integer, and it is returned. +Return Next Positive Integer if All Elements Are in Place, +If all elements are in their correct positions, the function returns the next positive integer after the maximum element in the array (n + 1). +*/ + + +/** + * @param {number[]} nums + * @return {number} + */ +var firstMissingPositive = function(nums) { + const n = nums.length; + + for (let i = 0; i < n; i++) + while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) + [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]; + + for (let i = 0; i < n; i++) + if (nums[i] !== i + 1) + return i + 1; + + return n + 1; +}; + +module.exports.firstMissingPositive = firstMissingPositive; \ No newline at end of file diff --git a/LeetcodeProblemsTests/Algorithms/easy/Best_Time_to_buy_and_sell_stock_Test.js b/LeetcodeProblemsTests/Algorithms/easy/Best_Time_to_buy_and_sell_stock_Test.js new file mode 100644 index 0000000..db97988 --- /dev/null +++ b/LeetcodeProblemsTests/Algorithms/easy/Best_Time_to_buy_and_sell_stock_Test.js @@ -0,0 +1,15 @@ +const assert = require("assert"); +const maxProfitEqual = require("../../../LeetcodeProblems/Algorithms/easy/Best_Time_to_buy_and_sell_stock").maxProfit; + +function test() { + assert.deepEqual( + maxProfit([7,1,5,3,6,4]), + 5 + ); + assert.deepEqual( + maxProfit([7,6,4,3,1]), + 0 + ); +} + +module.exports.test = test; \ No newline at end of file diff --git a/LeetcodeProblemsTests/Algorithms/hard/First_Missing_Positive_Test.js b/LeetcodeProblemsTests/Algorithms/hard/First_Missing_Positive_Test.js new file mode 100644 index 0000000..8662c2c --- /dev/null +++ b/LeetcodeProblemsTests/Algorithms/hard/First_Missing_Positive_Test.js @@ -0,0 +1,19 @@ +const assert = require("assert"); +const bitReverseToMakeNumberEqual = require("../../../LeetcodeProblems/Algorithms/hard/First_Missing_Positive").firstMissingPositive; + +function test() { + assert.deepEqual( + firstMissingPositive([1,2,0]), + 3 + ); + assert.deepEqual( + firstMissingPositive([3,4,-1,1]), + 2 + ); + assert.deepEqual( + firstMissingPositive([7,8,9,11,12]), + 1 +); +} + +module.exports.test = test; \ No newline at end of file diff --git a/README.md b/README.md index d03fae8..7e83652 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ The solutions are located under `/LeetcodeProblems`. Each problem has a test fil | Name | Level | Link | |----------------------------------------------------------------------------------------------------------------------------------------------------------------|--------|---------------------------------------------------------------------------------------------------------------------| | [Edit Distance ](/LeetcodeProblems/Algorithms/hard/Edit_Distance.js) | Hard | https://leetcode.com/problems/edit-distance/ | +| [First Missing Positive ](/LeetcodeProblems/Algorithms/hard/First_Missing_Positive.js) | Hard | https://leetcode.com/problems/first-missing-positive/ | | [Remove Invalid Parentheses ](/LeetcodeProblems/Algorithms/hard/Remove_Invalid_Parentheses.js) | Hard | https://leetcode.com/problems/remove-invalid-parentheses/ | | [Longest Consecutive Sequence ](/LeetcodeProblems/Algorithms/hard/Longest_Consecutive_Sequence.js) | Hard | https://leetcode.com/problems/longest-consecutive-sequence/ | | [Minimum Window Substring ](/LeetcodeProblems/Algorithms/hard/Minimum_Window_Substring.js) | Hard | https://leetcode.com/problems/minimum-window-substring/ | @@ -72,6 +73,7 @@ The solutions are located under `/LeetcodeProblems`. Each problem has a test fil | [Gas Station](/LeetcodeProblems/Algorithms/medium/GasStation/index.js) | Medium | https://leetcode.com/problems/gas-station/description/ | | [K Closest Points to Origin](/LeetcodeProblems/Algorithms/medium/K_Closest_Points_to_Origin.js/) | Medium | https://leetcode.com/problems/k-closest-points-to-origin/ | [BestTimeToBuy](LeetcodeProblems/Algorithms/easy/Best_Time_To_Buy_And_Sell_Stock_II.js) | Medium | https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii | +| [Best Time to Buy and Sell Stock](/LeetcodeProblems/Algorithms/easy/Best_Time_to_buy_and_sell_stock.js) | Easy | https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ | [Flood Fill ](/LeetcodeProblems/Algorithms/easy/Flood_Fill.js) | Easy | https://leetcode.com/problems/flood-fill/ | | [Implement stack using queues ](/LeetcodeProblems/Algorithms/easy/Implement_stack_using_queues.js) | Easy | https://leetcode.com/problems/implement-stack-using-queues/ | | [Number of Segments in a String ](/LeetcodeProblems/Algorithms/easy/Number_of_Segments_in_a_String.js) | Easy | https://leetcode.com/problems/number-of-segments-in-a-string/ | @@ -100,6 +102,7 @@ The solutions are located under `/LeetcodeProblems`. Each problem has a test fil | Algoritmhs | | - | | [Heap Sort](/SortingAlgorithms/heapSort.js) | +| [Merge Sort](/SortingAlgorithms/mergeSort.js) | | [Quick Sort](/SortingAlgorithms/QuickSort.js) | ### Databases diff --git a/SortingAlgorithms/mergeSort.js b/SortingAlgorithms/mergeSort.js new file mode 100644 index 0000000..9686427 --- /dev/null +++ b/SortingAlgorithms/mergeSort.js @@ -0,0 +1,39 @@ +function merge(leftArr, rightArr) { + let leftInd = 0, rightInd = 0; + const sortedArr = []; + + while(leftInd < leftArr.length && rightInd < rightArr.length) { + if (leftArr[leftInd] < rightArr[rightInd]) { + sortedArr.push(leftArr[leftInd]); + leftInd++; + } else { + sortedArr.push(rightArr[rightInd]); + rightInd++; + } + } + + // join leftover values from left array or right array + return sortedArr.concat(leftArr.slice(leftInd)).concat(rightArr.slice(rightInd)); +} + +const mergeSort = (arr) => { + if (arr.length <= 1) { + return arr; + } + + const mid = Math.floor(arr.length / 2); + const leftArr = mergeSort(arr.slice(0, mid)); + const rightArr = mergeSort(arr.slice(mid)); + + return merge(leftArr, rightArr); +}; + +console.log(mergeSort([4,12,5,3,78,12,133,32, 1000, 4000])); +console.log(mergeSort([14, 1, 10, 2, 3, 5, 6, 4, 7, 11, 12, 13])); +console.log(mergeSort([])); +console.log(mergeSort([1])); +console.log(mergeSort([2, 1])); +console.log(mergeSort([1,7,2,3,4,1,10,2,3,4,5])); +console.log(mergeSort(["One Piece", "One-Punch Man", "My Hero Academia", "Jujutsu Kaisen", "Death Note", "Fullmetal Alchemist: Brotherhood", "Akame ga Kill", "Bleach", "Black Clover"])); + +module.exports.mergeSort = mergeSort; diff --git a/SortingAlgorithmsTest/mergeSort_Test.js b/SortingAlgorithmsTest/mergeSort_Test.js new file mode 100644 index 0000000..c7d2ed7 --- /dev/null +++ b/SortingAlgorithmsTest/mergeSort_Test.js @@ -0,0 +1,27 @@ +const assert = require("assert"); +const mergeSort = require("../SortingAlgorithms/mergeSort").mergeSort; + +var test = function () { + assert.deepEqual( + [ 3, 4, 5, 12, 12, 32, 78, 133, 1000, 4000 ], + mergeSort([4, 12, 5, 3, 78, 12, 133, 32, 1000, 4000]) + ); + + assert.deepEqual( + [1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14], + mergeSort([14, 1, 10, 2, 3, 5, 6, 4, 7, 11, 12, 13]) + ); + + assert.deepEqual([], mergeSort([])); + assert.deepEqual([1], mergeSort([1])); + assert.deepEqual([1, 2], mergeSort([2, 1])); + assert.deepEqual([1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 10], mergeSort([1,7,2,3,4,1,10,2,3,4,5]) + ); + + assert.deepEqual( + ["Akame ga Kill", "Black Clover", "Bleach", "Death Note", "Fullmetal Alchemist: Brotherhood", "Jujutsu Kaisen", "My Hero Academia", "One Piece", "One-Punch Man"], + mergeSort(["One Piece", "One-Punch Man", "My Hero Academia", "Jujutsu Kaisen", "Death Note", "Fullmetal Alchemist: Brotherhood", "Akame ga Kill", "Bleach", "Black Clover"]) + ); +}; + +module.exports.test = test; diff --git a/Test.js b/Test.js index f1c8c87..7ac738f 100644 --- a/Test.js +++ b/Test.js @@ -5,13 +5,15 @@ const fs = require("fs"); const PROBLEMS_FOLDERS = [ "./LeetcodeProblems/Algorithms/easy/", "./LeetcodeProblems/Algorithms/medium/", - "./LeetcodeProblems/Algorithms/hard/" + "./LeetcodeProblems/Algorithms/hard/", + "./SortingAlgorithms/" ]; const TESTS_FOLDERS = [ "./LeetcodeProblemsTests/Algorithms/easy/", "./LeetcodeProblemsTests/Algorithms/medium/", - "./LeetcodeProblemsTests/Algorithms/hard/" + "./LeetcodeProblemsTests/Algorithms/hard/", + "./SortingAlgorithmsTest/" ]; const REGEX_PATTERN_HIDDEN_FILES = /(^|\/)\.[^\/\.]/g; diff --git a/package-lock.json b/package-lock.json index 9d02572..30e3f79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -596,9 +596,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -1364,9 +1364,9 @@ "dev": true }, "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "requires": { "argparse": "^2.0.1"