From 4cd18dcc8e33598088d365eb246bd0bebeb50861 Mon Sep 17 00:00:00 2001 From: Abhishek Ghosh Date: Sun, 22 Dec 2024 19:28:29 +0530 Subject: [PATCH] commit --- README-old.md | 7 +- resources/arrays.md | 11 +- resources/dynamic-programming.md | 1 + resources/greedy.md | 3 +- resources/hashing.md | 1 + resources/special-problems.md | 21 ++- resources/stack.md | 9 +- src/com/problems/array/FourSum.java | 17 ++- ...erationsToMakeElementsInArrayDistinct.java | 105 +++++++++++++ ...mNumberOfSwapsToMakeTheStringBalanced.java | 52 +++++++ ...berOfPairsOfInterchangeableRectangles.java | 86 +++++++++++ src/com/problems/array/SortZeroOneTwo.java | 2 +- src/com/problems/array/ThreeSum.java | 6 +- .../dp/CountPathsWithTheGivenXORValue.java | 140 ++++++++++++++++++ .../problems/dp/SumOfGoodSubsequences.java | 5 +- ...mberOfDistinctElementsAfterOperations.java | 64 ++++++++ src/com/problems/queue/QueueUsingStack.java | 4 +- src/com/problems/stack/BaseballGame.java | 79 ++++++++++ .../problems/stack/MakeTheStringGreat.java | 31 +++- src/com/problems/stack/StackUsingQueue.java | 2 +- src/com/problems/stack/ValidParenthesis.java | 39 +---- 21 files changed, 623 insertions(+), 62 deletions(-) create mode 100644 src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java create mode 100644 src/com/problems/array/MinimumNumberOfSwapsToMakeTheStringBalanced.java create mode 100644 src/com/problems/array/NumberOfPairsOfInterchangeableRectangles.java create mode 100644 src/com/problems/dp/CountPathsWithTheGivenXORValue.java create mode 100644 src/com/problems/greedy/MaximumNumberOfDistinctElementsAfterOperations.java create mode 100644 src/com/problems/stack/BaseballGame.java diff --git a/README-old.md b/README-old.md index da5f30d..3f26c23 100644 --- a/README-old.md +++ b/README-old.md @@ -32,12 +32,7 @@ - bit-manipulation - - - [3 Sum : Find triplets that add up to a zero](/src/com/problems/array/ThreeSum.java) - - two-pointer - - hashing - - [4 Sum / Find Quads that add up to a target value](/src/com/problems/array/FourSum.java) - - two-pointer - - hashing + - [Insert Delete GetRandom O(1)](/src/com/problems/array/RandomizedSetProblem.java) diff --git a/resources/arrays.md b/resources/arrays.md index 89cb13e..3f7b8f1 100644 --- a/resources/arrays.md +++ b/resources/arrays.md @@ -9,13 +9,19 @@ ### General +- [Two Sum : Check if a pair with given sum exists in Array](/src/com/problems/array/TwoSum.java) +- [3 Sum : Find triplets that add up to a zero](/src/com/problems/array/ThreeSum.java) +- [4 Sum / Find Quads that add up to a target value](/src/com/problems/array/FourSum.java) + - [Contains Duplicate](/src/com/problems/hashing/ContainsDuplicate.java) - [Contains Duplicate II](/src/com/problems/hashing/ContainsDuplicate2.java) + - [Replace Elements with Greatest Element on Right Side](/src/com/problems/array/ReplaceElementsWithGreatestElementOnRightSide.java) -- [Two Sum : Check if a pair with given sum exists in Array](/src/com/problems/array/TwoSum.java) + - [Program to generate Pascal’s Triangle](/src/com/problems/array/PascalTriangle.java) - [Program to generate Pascal’s Triangle one row](/src/com/problems/array/PascalTriangleOneRow.java) - [Program to generate Pascal’s Triangle one element](/src/com/problems/array/PascalTriangleOneElement.java) + - [Remove Element](/src/com/problems/array/RemoveElement.java) - [Majority Element I | Find the Majority Element that occurs more than N/2 times](/src/com/problems/array/MajorityElements1.java) - [Majority Element II | Find the elements that appear more than N/3 times in the array](/src/com/problems/array/MajorityElements2.java) @@ -34,7 +40,10 @@ - [Valid Sudoku](/src/com/problems/array/ValidSudoku.java) - [Longest Consecutive Sequence in an Array](/src/com/problems/array/LongestConsecutiveSequence.java) - [Sort an array of 0's 1's and 2's](/src/com/problems/array/SortZeroOneTwo.java) +- [Minimum Number of Operations to Make Elements in Array Distinct](/src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java) +- [Minimum Number of Swaps to Make The String Balanced](/src/com/problems/array/MinimumNumberOfSwapsToMakeTheStringBalanced.java) +- [Number of Pairs of Interchangeable Rectangles](/src/com/problems/array/NumberOfPairsOfInterchangeableRectangles.java) ### Swap sort diff --git a/resources/dynamic-programming.md b/resources/dynamic-programming.md index f6c0068..af8027f 100644 --- a/resources/dynamic-programming.md +++ b/resources/dynamic-programming.md @@ -100,4 +100,5 @@ - [Maximize Total Cost of Alternating Subarrays](/src/com/problems/dp/MaximizeTotalCostOfAlternatingSubarrays.java) - [Minimum Cost for Cutting Cake I](/src/com/problems/dp/MinimumCostForCuttingCakeI.java) - [Sum of Good Subsequences](/src/com/problems/dp/SumOfGoodSubsequences.java) +- [Count Paths With the Given XOR Value](/src/com/problems/dp/CountPathsWithTheGivenXORValue.java) diff --git a/resources/greedy.md b/resources/greedy.md index 3ac8c7d..4b00cd7 100644 --- a/resources/greedy.md +++ b/resources/greedy.md @@ -17,4 +17,5 @@ - [Non-overlapping Intervals](/src/com/problems/greedy/NonOverlappingIntervals.java) - [Increasing Triplet Subsequence](/src/com/problems/greedy/IncreasingTripletSubsequence.java) - [Minimum Number of Pushes to Type Word I](/src/com/problems/greedy/MinimumNumberOfPushesToTypeWord1.java) -- [Minimum Number of Pushes to Type Word II](/src/com/problems/greedy/MinimumNumberOfPushesToTypeWord2.java) \ No newline at end of file +- [Minimum Number of Pushes to Type Word II](/src/com/problems/greedy/MinimumNumberOfPushesToTypeWord2.java) +- [Maximum Number of Distinct Elements After Operations](/src/com/problems/greedy/MaximumNumberOfDistinctElementsAfterOperations.java) \ No newline at end of file diff --git a/resources/hashing.md b/resources/hashing.md index 277267a..074722b 100644 --- a/resources/hashing.md +++ b/resources/hashing.md @@ -31,6 +31,7 @@ - [Encode and Decode TinyURL](/src/com/problems/array/EncodeAndDecodeTinyURL.java) - [Brick Wall](/src/com/problems/array/BrickWall.java) - [Unique Length 3 Palindromic Subsequences](/src/com/problems/array/UniqueLength3PalindromicSubsequences.java) +- [Minimum Number of Operations to Make Elements in Array Distinct](/src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java) diff --git a/resources/special-problems.md b/resources/special-problems.md index 094e40c..72d6e60 100644 --- a/resources/special-problems.md +++ b/resources/special-problems.md @@ -12,4 +12,23 @@ - [Jump Game 6](/src/com/problems/special/jumpgame/JumpGame6.java) - [Jump Game 7](/src/com/problems/special/jumpgame/JumpGame7.java) - [Frog Jump 1](/src/com/problems/special/jumpgame/FrogJump1.java) -- [Frog Jump 2](/src/com/problems/special/jumpgame/FrogJump2.java) \ No newline at end of file +- [Frog Jump 2](/src/com/problems/special/jumpgame/FrogJump2.java) + +### Resources + +### Stone Game + +- [Stone game] +- [Stone game II] +- [Stone game III] +- [Stone game IV] +- [Stone game V] +- [Stone game VI] +- [Stone game VII] +- [Stone game VIII] +- [Stone game IX] + +### Resources + +- [Master Game Theory / Geeksforgeeks](https://www.youtube.com/playlist?list=PLM68oyaqFM7RqV8GBCMGsmwyFxUVr36tx) +- [Game Theory - Level 3 / pepcoding](https://www.youtube.com/playlist?list=PL-Jc9J83PIiENC1X16gjxjaIbSXBr8C6e) \ No newline at end of file diff --git a/resources/stack.md b/resources/stack.md index 57e3e68..94051c4 100644 --- a/resources/stack.md +++ b/resources/stack.md @@ -11,16 +11,21 @@ - [Implement Stack using Arrays](/src/com/problems/stack/Stack.java) - [Implement Stack using Queue](/src/com/problems/stack/StackUsingQueue.java) - [Implement stack using Linkedlist](/src/com/problems/stack/StackUsingLinkedlist.java) +- [Implement Queue using Stack](/src/com/problems/queue/QueueUsingStack.java) +- [Implement Min Stack](/src/com/problems/stack/MinStack.java) + - [Valid Parentheses](/src/com/problems/stack/ValidParenthesis.java) - [Longest Valid Parentheses](/src/com/problems/stack/LongestValidParenthesis.java) -- [Implement Min Stack](/src/com/problems/stack/MinStack.java) +- [Baseball Game](/src/com/problems/stack/BaseballGame.java) +- [Make The String Great](/src/com/problems/stack/MakeTheStringGreat.java) + - [Infix to Postfix](/src/com/problems/stack/InfixToPostfix.java) - [Postfix to Infix](/src/com/problems/stack/PostfixToInfix.java) - [Infix To Prefix](/src/com/problems/stack/InfixToPrefix.java) - [Prefix to Infix](/src/com/problems/stack/PrefixToInfix.java) - [Prefix to Postfix](/src/com/problems/stack/PrefixToPostfix.java) - [Postfix to Prefix](/src/com/problems/stack/PostfixToPrefix.java) -- [Make The String Great](/src/com/problems/stack/MakeTheStringGreat.java) + - [Next Greater Element](/src/com/problems/stack/NextGreaterElement.java) - [Next Greater Element for different array](/src/com/problems/stack/NextGreaterElementForDifferentArray.java) - [Next Greater Element in a Circle](/src/com/problems/stack/NextGreaterElementInCircle.java) diff --git a/src/com/problems/array/FourSum.java b/src/com/problems/array/FourSum.java index d70c89d..afc5fff 100644 --- a/src/com/problems/array/FourSum.java +++ b/src/com/problems/array/FourSum.java @@ -1,6 +1,9 @@ package com.problems.array; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; import java.util.stream.Collectors; /* @@ -15,6 +18,8 @@ * * https://takeuforward.org/data-structure/4-sum-find-quads-that-add-up-to-a-target-value/ * */ + +// Tags: Arrays, Two Pointers public class FourSum { public static void main(String[] args) { @@ -44,14 +49,14 @@ private static void type2() { // we have to skip this nums[i] if ((long) nums[i] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) continue; for (int j = i + 1; j <= n - 3; j++) { - //if there is a series of duplicates then it will just take the first time when j==i+1 + //if there is a series of duplicates, then it will just take the first time when j==i+1 //when j>i+1 then for all duplicate value will be skipped if (j > i + 1 && nums[j] == nums[j - 1]) continue; - // in a series left most elements are the smallest - // if sum of i and j to j+2 elements are less than target then there is not point to check + // in a series left, most elements are the smallest + // if the sum of i and j to j+2 elements are less than target then there is no point to check if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target ) break; - // if nums[i] plus nums[j] and last 2 numbers are less than target - // than means nums[j] is useless as last 2 numbers are the highest + // if nums[i] plus nums[j] and the last 2 numbers are less than target + // than means nums[j] is useless as the last 2 numbers are the highest, // we have to skip this nums[j] if ((long) nums[i] + nums[j] + nums[n - 2] + nums[n - 1] < target ) continue; left = j + 1; diff --git a/src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java b/src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java new file mode 100644 index 0000000..257cbf5 --- /dev/null +++ b/src/com/problems/array/MinimumNumberOfOperationsToMakeElementsInArrayDistinct.java @@ -0,0 +1,105 @@ +package com.problems.array; + +/* + * Problem link: + * https://leetcode.com/problems/minimum-number-of-operations-to-make-elements-in-array-distinct/ + * + * Solution link : + * + */ +public class MinimumNumberOfOperationsToMakeElementsInArrayDistinct { + public static void main(String[] args) { + type1(); + type2(); + type3(); + } + + // rather going from first if we go from the last + // if we go from the last till freq of any element is greater than 1 + private static void type3() { + int[] nums = {1, 2, 3, 4, 2, 3, 3, 5, 7}; + int ans = minimumOperations3(nums); + System.out.println(ans); + } + + private static int minimumOperations3(int[] nums) { + int n = nums.length; + int[] freq = new int[101]; + int rem = (n % 3); + int parts = (n / 3) + (rem > 0 ? 1 : 0); + int i = n - 1; + // checking for the first part individually if there is any reminder + while (rem > 0) { + rem--; + int num = nums[i--]; + freq[num]++; + if (freq[num] == 2) return parts; + } + // this means n has a reminder but that part only contained the unique elements, + // so we will decrement the part needed + if (n % 3 != 0) parts--; + + // checking for the remaining parts which is multiple of length 3 + while (parts > 0) { + int d = 3; + while (d > 0) { + int num = nums[i--]; + freq[num]++; + if (freq[num] == 2) return parts; + d--; + } + parts--; + } + return parts; + } + + // hashing approach + // we will store the freq of the numbers and as we well as store a variable to keep track + // the number of non-unique elements. so that we do not need to go through the entire freq map or array + // every time, to check how many non-unique are left + private static void type2() { + int[] nums = {1, 2, 3, 4, 2, 3, 3, 5, 7}; + int ans = minimumOperations2(nums); + System.out.println(ans); + } + + public static int minimumOperations2(int[] nums) { + int n = nums.length; + int count = 0; + int[] freq = new int[101]; + int nonUnique = 0; + for (int num : nums) { + freq[num]++; + // if freq 2, that means it is non-unique, + // we do not need to check for > 2 as once it is non-unique, it will stay as non-unique + if (freq[num] == 2) nonUnique++; + } + // now we will loop till non-unique count is 0 + // (non-unique-count > 0) means there should be at least 2 elements in the array + int i = 0; + while (nonUnique > 0) { + count++; + int first = nums[i], second = nums[i + 1]; + // decreasing the freq of first and checking if the freq reduced to 1 + freq[first]--; + if (freq[first] == 1) nonUnique--; + // decreasing the freq of first and checking if the freq reduced to 1 + freq[second]--; + if (freq[second] == 1) nonUnique--; + // checking if there is the third element or not, if it has third then only we will check for it + if (i + 2 < n) { + int third = nums[i + 2]; + freq[third]--; + if (freq[third] == 1) nonUnique--; + } + i = i + 3; + } + return count; + } + + + // brute force approach + private static void type1() { + } + +} diff --git a/src/com/problems/array/MinimumNumberOfSwapsToMakeTheStringBalanced.java b/src/com/problems/array/MinimumNumberOfSwapsToMakeTheStringBalanced.java new file mode 100644 index 0000000..7de006b --- /dev/null +++ b/src/com/problems/array/MinimumNumberOfSwapsToMakeTheStringBalanced.java @@ -0,0 +1,52 @@ +package com.problems.array; + +/* + * + * problem links : + * https://leetcode.com/problems/minimum-number-of-swaps-to-make-the-string-balanced/description/ + * + * Solution link : + * https://www.youtube.com/watch?v=3YDBT9ZrfaU + * + * https://neetcode.io/solutions/minimum-number-of-swaps-to-make-the-string-balanced + * */ + + +// Tags: Arrays, Two Pointers, String, Stack, Greedy +public class MinimumNumberOfSwapsToMakeTheStringBalanced { + public static void main(String[] args) { + type1(); + } + + // todo check this solution again + // We will be a little greedy here + // The total number of unmatched opening brackets at the end will tell us how many swaps are necessary to balance the string + // so, we keep track the number of unmatched closing brackets. + // Each swap can fix two unmatched brackets, so the minimum number of swaps required is (unmatched+1)/2 + private static void type1() { + String s = "]][][["; + int ans = minSwaps3(s); + System.out.println(ans); + } + + public static int minSwaps3(String s) { + int imbalance = 0; // This variable tracks the number of unmatched closing brackets + int openBrackets = 0; // This variable tracks the number of unmatched opening brackets + // Iterate through each character in the string + for (char c : s.toCharArray()) { + if (c == '[') { + openBrackets++; // Increment for an opening bracket + } else { // c == ']' + if (openBrackets > 0) { + openBrackets--; // Match with an opening bracket + } else { + imbalance++; // Unmatched closing bracket + } + } + } + // Each swap can fix two imbalances, hence divide by 2 + return (imbalance + 1) / 2; + } + + +} diff --git a/src/com/problems/array/NumberOfPairsOfInterchangeableRectangles.java b/src/com/problems/array/NumberOfPairsOfInterchangeableRectangles.java new file mode 100644 index 0000000..cd03bb6 --- /dev/null +++ b/src/com/problems/array/NumberOfPairsOfInterchangeableRectangles.java @@ -0,0 +1,86 @@ +package com.problems.array; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/* + * + * problem links : + * https://leetcode.com/problems/number-of-pairs-of-interchangeable-rectangles/description/ + * + * Solution link : + * https://www.youtube.com/watch?v=lEQ8ZlLOuyQ + * + * https://neetcode.io/solutions/number-of-pairs-of-interchangeable-rectangles + * */ +public class NumberOfPairsOfInterchangeableRectangles { + public static void main(String[] args) { + type1(); + type2(); + } + + // not the most optimized approach + // as an array is easier and less time-consuming to handle, so we will use an array to store the ratios + // we will create an array of double as the same size of the rectangles. + // then sort that array, so same ratios will come in together + // we will count that then apply the f*(f-1)/2 + private static void type2() { + int[][] rectangles = {{4, 8}, {3, 6}, {10, 20}, {5, 30}}; + long ans = interchangeableRectangles2(rectangles); + System.out.println(ans); + } + + private static long interchangeableRectangles2(int[][] rectangles) { + int n = rectangles.length; + // storing all the ratios + double[] ratios = new double[n]; + int i = 0; + for (int[] rec : rectangles) { + ratios[i++] = (double) rec[0] / (double) rec[1]; + } + Arrays.sort(ratios); + // now counting for all the ratios + double prev = 0; + long count = 0, f = 0; + for (i = 0; i <= n; i++) { + if (i == n || prev != ratios[i]) { + count += (f * (f - 1)) / 2; + if (i != n) { + prev = ratios[i]; + f = 1; + } + } else { + f++; + } + } + return count; + } + + // brute force approach using a hashmap + // we will store the ratios and their freq in a map + // if there are f number of rectangles with the same ratios. + // if 2 rectangles can interchange, so the problem is to choose 2 among f options + // which will be fC2 ⇒ f*(f-1)/2 + private static void type1() { + int[][] rectangles = {{4, 8}, {3, 6}, {10, 20}, {5, 30}}; + long ans = interchangeableRectangles1(rectangles); + System.out.println(ans); + } + + public static long interchangeableRectangles1(int[][] rectangles) { + // now counting for all the ratios + Map freq = new HashMap<>(); + for (int[] rec : rectangles) { + double ratio = (double) rec[0] / (double) rec[1]; + freq.put(ratio, 1L + freq.getOrDefault(ratio, 0L)); + } + long count = 0; + for (Map.Entry entry : freq.entrySet()) { + long f = entry.getValue(); + if (f == 1) continue; + count += (f * (f - 1)) / 2; + } + return count; + } +} diff --git a/src/com/problems/array/SortZeroOneTwo.java b/src/com/problems/array/SortZeroOneTwo.java index 7465a32..cfc449c 100644 --- a/src/com/problems/array/SortZeroOneTwo.java +++ b/src/com/problems/array/SortZeroOneTwo.java @@ -21,7 +21,7 @@ * https://neetcode.io/solutions/sort-colors * */ -// Tags : Arrays, sorting, hashing, Dutch national flag algorithm 3 pointer +// Tags: Arrays, sorting, hashing, Dutch national flag algorithm 3 pointer public class SortZeroOneTwo { public static void main(String[] args) { diff --git a/src/com/problems/array/ThreeSum.java b/src/com/problems/array/ThreeSum.java index 276025c..8067965 100644 --- a/src/com/problems/array/ThreeSum.java +++ b/src/com/problems/array/ThreeSum.java @@ -19,9 +19,9 @@ * Blogs : * https://takeuforward.org/data-structure/3-sum-find-triplets-that-add-up-to-a-zero/ * - * Tags: - * Two-Pointers * */ + +// Tags: array, two pointers public class ThreeSum { public static void main(String[] args) { @@ -52,7 +52,7 @@ private static List> threeSum2(int[] nums) { // and num[i] is not capable to generate 0 even with the highest of numbers on that array if (nums[i] + nums[n - 2] + nums[n - 1] < 0) continue; // as nums[i] + nums[i + 1] + nums[i + 2] will be the smallest in this series - // if sum of first 3 is greater than 0 then the sum for remaining items will also be greater than 0, + // if the sum of first 3 is greater than 0 then the sum for remaining items will also be greater than 0, // so we will break here if (nums[i] + nums[i + 1] + nums[i + 2] > 0) break; left = i + 1; diff --git a/src/com/problems/dp/CountPathsWithTheGivenXORValue.java b/src/com/problems/dp/CountPathsWithTheGivenXORValue.java new file mode 100644 index 0000000..d5f4677 --- /dev/null +++ b/src/com/problems/dp/CountPathsWithTheGivenXORValue.java @@ -0,0 +1,140 @@ +package com.problems.dp; + +import java.util.HashMap; +import java.util.Map; + +/* + * Problem link: + * https://leetcode.com/problems/count-paths-with-the-given-xor-value/description/ + * + * Solution link : + * + */ +public class CountPathsWithTheGivenXORValue { + public static void main(String[] args) { + type1(); + type2(); + type3(); + } + + static int mod = (int) 1e9 + 7; + + // same as before top-down approach with the same dp table + private static void type3() { + int[][] grid = {}; + int k = 11; + int ans = countPathsWithXorValue3(grid, k); + System.out.println(ans); + } + + + static int countPathsWithXorValue3(int[][] grid, int k) { + int m = grid.length; + int n = grid[0].length; + + // Create a DP table where each cell contains a HashMap for XOR values + Map[][] dp = new Map[m][n]; + + // Initialize the DP table + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + dp[i][j] = new HashMap<>(); + } + } + // Starting point + dp[0][0].put(grid[0][0], 1); + // Fill the DP table + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + for (int xorValue : dp[i][j].keySet()) { + int count = dp[i][j].get(xorValue); + // Move right + if (j + 1 < n) { + int newXor = xorValue ^ grid[i][j + 1]; + dp[i][j + 1].put(newXor, (dp[i][j + 1].getOrDefault(newXor, 0) + count) % mod); + } + // Move down + if (i + 1 < m) { + int newXor = xorValue ^ grid[i + 1][j]; + dp[i + 1][j].put(newXor, (dp[i + 1][j].getOrDefault(newXor, 0) + count) % mod); + } + } + } + } + + // The result is the number of paths that reach the bottom-right corner with XOR equal to k + return dp[m - 1][n - 1].getOrDefault(k, 0); + } + + // same as before, but here we will use dynamic programming + // before creating and 2D array or map let's see what we need, actually. + // so there are (m*n) cells, and we can visit any cell in multiple possible ways, + // and all those ways will generate different xor values for that cell. + // so even for a single cell, there will be different xor and their total path counts. + // so in each cell we will create a map + private static void type2() { + int[][] grid = {{1, 3, 3, 3}, {0, 3, 3, 2}, {3, 0, 1, 1}}; + int k = 2; + int ans = countPathsWithXorValue2(grid, k); + System.out.println(ans); + } + + public static int countPathsWithXorValue2(int[][] grid, int k) { + int m = grid.length, n = grid[0].length; + // m*n cells have their individual maps + Map[][] dp = new Map[m][n]; + return countPathsWithXorValue(m - 1, n - 1, grid, k, 0, dp); + } + + static int countPathsWithXorValue(int i, int j, int[][] grid, int k, int xor, Map[][] dp) { + if (i == -1 || j == -1) return 0; + // calculating the xor value + xor = xor ^ grid[i][j]; + // if there is a map for the current cell and xor value is present in that map, + // then we will return from that + if (dp[i][j] != null && dp[i][j].containsKey(xor)) return dp[i][j].get(xor); + // if we have reached to (0,0) and the xor value is k, then we will return 1 else 0 + if (i == 0 && j == 0) { + return (k == xor) ? 1 : 0; + } + // else we will go to the left or go up + int up = countPathsWithXorValue(i - 1, j, grid, k, xor, dp) % mod; + int left = countPathsWithXorValue(i, j - 1, grid, k, xor, dp) % mod; + int val = (up + left) % mod; + // if the cell is not initialized, then we will initialize and then put the current xor and count value + if (dp[i][j] == null) dp[i][j] = new HashMap<>(); + dp[i][j].put(xor, val); + return val; + } + + // brute force approach using normal recursion + // rather starting from the (0,0) we will start from + // we will start from the (m-1,n-1) and go till (0,0) + private static void type1() { + int[][] grid = {{1, 3, 3, 3}, {0, 3, 3, 2}, {3, 0, 1, 1}}; + int k = 2; + int ans = countPathsWithXorValue1(grid, k); + System.out.println(ans); + } + + + public static int countPathsWithXorValue1(int[][] grid, int k) { + int m = grid.length, n = grid[0].length; + Map[][] dp = new Map[m][n]; + return countPathsWithXorValue(m - 1, n - 1, grid, k, 0); + } + + static int countPathsWithXorValue(int i, int j, int[][] grid, int k, int xor) { + if (i == -1 || j == -1) return 0; + xor = xor ^ grid[i][j]; + // if we have reached to (0,0) and the xor value is k, then we will return 1 else 0 + if (i == 0 && j == 0) { + return (k == xor) ? 1 : 0; + } + // else we will go to the left or go up + int up = countPathsWithXorValue(i - 1, j, grid, k, xor) % mod; + int left = countPathsWithXorValue(i, j - 1, grid, k, xor) % mod; + // and return the total possibilities + return (up + left) % mod; + } +} diff --git a/src/com/problems/dp/SumOfGoodSubsequences.java b/src/com/problems/dp/SumOfGoodSubsequences.java index ec0f2fc..8f999c5 100644 --- a/src/com/problems/dp/SumOfGoodSubsequences.java +++ b/src/com/problems/dp/SumOfGoodSubsequences.java @@ -1,12 +1,15 @@ package com.problems.dp; /* - * Problem link : + * Problem link: * https://leetcode.com/problems/sum-of-good-subsequences/description/ * Course Schedule: * * * Solution link : + * + * + * */ public class SumOfGoodSubsequences { public static void main(String[] args) { diff --git a/src/com/problems/greedy/MaximumNumberOfDistinctElementsAfterOperations.java b/src/com/problems/greedy/MaximumNumberOfDistinctElementsAfterOperations.java new file mode 100644 index 0000000..b66f376 --- /dev/null +++ b/src/com/problems/greedy/MaximumNumberOfDistinctElementsAfterOperations.java @@ -0,0 +1,64 @@ +package com.problems.greedy; + +import java.util.Arrays; + +/* + * Problem link : + * https://leetcode.com/problems/maximum-number-of-distinct-elements-after-operations/ + * + * Solution link : + * + */ +public class MaximumNumberOfDistinctElementsAfterOperations { + public static void main(String[] args) { + type1(); + } + + // we will use a greedy method here + // rather than changing duplicate elements + // if we try to change all the elements + // this sounds more work, but it makes changing safe for other elements. + // a num can be changed into [num-k, num+k] + // we will take a side we will try to make a num as low as possible + // or as big as possible. let's take an example. if the X is the max of nums, + // if we make X to X+k, then it would not interfere with other numbers. + // if there are other X then we can change them to [ X+k-1, X+k-2, ... X-k ], + // so we will keep track of the last converted number + // and check if we can convert the current num to (lastConverted - 1) + // if (lastConverted - 1) falls in between (num-k) to (num+k) then we can change the curr num to (lastConverted - 1) + // but if the num+k <<<< (lastConverted - 1) + // then we can change the current num to num+k again + // todo but before everything we need to sort the nums array, + // so that all the numbers will come one by one in decreasing order and then last converted numbers will also + // come in order and no number will intersect + private static void type1() { + int[] nums = {1, 2, 2, 3, 3, 4}; + int k = 2; + int ans = maxDistinctElements1(nums, k); + System.out.println(ans); + + } + + public static int maxDistinctElements1(int[] nums, int k) { + Arrays.sort(nums); + int n = nums.length; + // we will convert the last item as a seed value + int lastConverted = nums[n - 1] + k; + int count = 1; + // we will start from n-2 and check if we can convert (lastConverted - 1) or (num+k) + for (int i = n - 2; i >= 0; i--) { + int num = nums[i]; + int upperBound = num + k, lowerBound = num - k; + // if curr num is convertible to (lastConverted - 1), then we will convert it + if (lowerBound <= (lastConverted - 1) && (lastConverted - 1) <= upperBound) { + lastConverted--; + count++; + } else if (upperBound < (lastConverted - 1)) { + // num+k <<<< (lastConverted - 1), so we will reset the lastConverted with num+k + lastConverted = upperBound; + count++; + } + } + return count; + } +} diff --git a/src/com/problems/queue/QueueUsingStack.java b/src/com/problems/queue/QueueUsingStack.java index 7f9de2c..192e338 100644 --- a/src/com/problems/queue/QueueUsingStack.java +++ b/src/com/problems/queue/QueueUsingStack.java @@ -3,14 +3,16 @@ import java.util.Stack; /* * Problem link : - * https://leetcode.com/problems/implement-queue-using-stacks/ + * https://leetcode.com/problems/implement-queue-using-stacks/description/ * https://www.naukri.com/code360/problems/day-25-:-queue-using-stack_799482 * * Solution link : * https://www.youtube.com/watch?v=tqQ5fTamIN4 * https://www.youtube.com/watch?v=3Et9MrMc02A + * https://www.youtube.com/watch?v=eanwa3ht3YQ * * https://takeuforward.org/data-structure/implement-queue-using-stack/ + * https://neetcode.io/solutions/implement-queue-using-stacks * */ public class QueueUsingStack { diff --git a/src/com/problems/stack/BaseballGame.java b/src/com/problems/stack/BaseballGame.java new file mode 100644 index 0000000..f84c408 --- /dev/null +++ b/src/com/problems/stack/BaseballGame.java @@ -0,0 +1,79 @@ +package com.problems.stack; + +import java.util.Stack; +/* + * Problem link : + * + * Solution link : + * + * + * + * */ + +// Tags : Stack, Array +public class BaseballGame { + public static void main(String[] args) { + type1(); + type2(); + } + + // using an array + // same as the previous type + private static void type2() { + String[] ops = {"5", "2", "C", "D", "+"}; + int ans = calPoints2(ops); + System.out.println(ans); + } + + private static int calPoints2(String[] ops) { + int n = ops.length; + int top = -1; + int[] st = new int[n]; + for (String op : ops) { + if ("+".equals(op)) { + int first = st[top]; + int second = st[top - 1]; + st[++top] = first + second; + } else if ("D".equals(op)) { + int last = st[top]; + st[++top] = 2 * last; + } else if ("C".equals(op)) { + top--; + } else { + st[++top] = Integer.parseInt(op); + } + } + int sum = 0; + for (int i = 0; i <= top; i++) sum += st[i]; + return sum; + } + + // Optimized approach using stack + private static void type1() { + String[] ops = {"5", "2", "C", "D", "+"}; + int ans = calPoints1(ops); + System.out.println(ans); + + } + + public static int calPoints1(String[] ops) { + Stack st = new Stack<>(); + for (String op : ops) { + if ("+".equals(op)) { + int first = st.pop(); + int second = st.peek(); + st.push(first); + st.push((first + second)); + } else if ("D".equals(op)) { + st.push(2 * st.peek()); + } else if ("C".equals(op)) { + st.pop(); + } else { + st.push(Integer.parseInt(op)); + } + } + int sum = 0; + while (!st.isEmpty()) sum += st.pop(); + return sum; + } +} diff --git a/src/com/problems/stack/MakeTheStringGreat.java b/src/com/problems/stack/MakeTheStringGreat.java index 2a7558b..8390ed6 100644 --- a/src/com/problems/stack/MakeTheStringGreat.java +++ b/src/com/problems/stack/MakeTheStringGreat.java @@ -19,13 +19,39 @@ public static void main(String[] args) { type2(); } - static int diff = 'a' - 'A'; + // using an array + // almost the same as previous. + // we will use the same array to store the characters, + // so we will use a prev variable here + // in place changing private static void type2() { + String s = "leEeetcode"; + String ans = makeGood2(s); + System.out.println(ans); + } + + private static String makeGood2(String s) { + int diff = 'a' - 'A'; + char[] arr = s.toCharArray(); + // instead of stack, we will use a variable + int prev = -1; + for (char ch : arr) { + if (prev != -1 && Math.abs(arr[prev] - ch) == diff) + prev--; + else + arr[++prev] = ch; + } + // we will use a string builder to store the result + StringBuilder sb = new StringBuilder(); + for (int i = 0; i <= prev; i++) sb.append(arr[i]); + return sb.toString(); } // brute force using stack - // we could use an array as stack + // we could use an array as stack, though. + // we will check the last character of stack if the difference is 'a' - 'A' + // then it is the same letter but different case, so we will pop it private static void type1() { String s = "leEeetcode"; String ans = makeGood1(s); @@ -34,6 +60,7 @@ private static void type1() { public static String makeGood1(String s) { + int diff = 'a' - 'A'; char[] arr = s.toCharArray(); Stack st = new Stack<>(); for (char ch : arr) { diff --git a/src/com/problems/stack/StackUsingQueue.java b/src/com/problems/stack/StackUsingQueue.java index 210b070..9d45ad8 100644 --- a/src/com/problems/stack/StackUsingQueue.java +++ b/src/com/problems/stack/StackUsingQueue.java @@ -4,7 +4,7 @@ import java.util.Queue; /* * Problem link : - * https://leetcode.com/problems/implement-stack-using-queues/ + * https://leetcode.com/problems/implement-stack-using-queues/description/ * https://www.naukri.com/code360/problems/stack-using-queue_795152 * * Solution link : diff --git a/src/com/problems/stack/ValidParenthesis.java b/src/com/problems/stack/ValidParenthesis.java index 4ed31e0..94c63c1 100644 --- a/src/com/problems/stack/ValidParenthesis.java +++ b/src/com/problems/stack/ValidParenthesis.java @@ -15,51 +15,18 @@ * https://takeuforward.org/data-structure/check-for-balanced-parentheses/ * * - * Tags : - * Stack * */ + +// Tags : Stack, String public class ValidParenthesis { public static void main(String[] args) { type1(); type2(); - type3(); - } - - private static void type3() { - String s = "()[]{}"; - boolean answer = isValid3(s); - System.out.println(answer); } - // similar to the previous approach with little difference - // here we are saving exactly opposite closing bracket of the opening bracket - private static boolean isValid3(String s) { - char[] stack = new char[s.length()]; - int top = 0; - for (char ch : s.toCharArray()) { - // we will add exactly opposite brackets for every opening brackets - switch (ch) { - case '(': - stack[top++] = ')'; - break; - case '{': - stack[top++] = '}'; - break; - case '[': - stack[top++] = ']'; - break; - default: - // if the stack is empty or the top character of the stack is not same as the current character - if (top == 0 || stack[--top] != ch) return false; - break; - } - } - // checking if the stack is empty or not - return (top == 0); - } - // exactly like the previous but here we are using normal array as stack + // exactly like the previous, but here we are using a normal array as stack private static void type2() { String s = "()[]{}"; boolean answer = isValid2(s);