From 0172c299c7cb3394ff8700c71c2cc00d24451994 Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 16:28:51 +0530 Subject: [PATCH 01/13] Added New Java file in Java/Misc --- Misc/largestRange.java | 46 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Misc/largestRange.java diff --git a/Misc/largestRange.java b/Misc/largestRange.java new file mode 100644 index 000000000000..fd61c38446d2 --- /dev/null +++ b/Misc/largestRange.java @@ -0,0 +1,46 @@ +import java.util.*; +public class largestRange +{ + // Finds the length of longest occurring consecutive numbers range in an array + public static int longestRange(int[] nums) + { + int longestRange = 0; + HashMap num = new HashMap<>(); // Stores a mapping of a number to whether the current number is part of a particular consecutive range or not + for(int x : nums) + num.put(x, true); + for(int x : nums) + { + if(!num.get(x)) + continue; + num.replace(x, false); + int currentRange=1; + int left = x - 1; + int right = x + 1; + while(num.containsKey(left)) // Search leftwards for consecutive range + { + num.replace(left, false); + currentRange+=1; + left--; + } + while(num.containsKey(right)) // Search rightwards for consecutive range + { + num.replace(right, false); + currentRange+=1; + right++; + } + if(currentRange > longestRange) // Store longest range at every interation + longestRange = currentRange; + } + return longestRange; + } + + public static void main(String[] args) { + // Testcases + assert longestRange(new int[]{1, 2, 3, 4, -1, 11, 10}) == 4; + // The longest consecutive number range is of length 4 i.e. {1, 2, 3, 4} + assert longestRange(new int[]{-1, 1, 3, 5, 7})==1; + // The longest consecutive number range is of length 1 i.e. any of the element alone + assert longestRange(new int[]{0, 1, 2, 3, 4, 7, 6, 5})==8; + // The longest consecutive number range is of length 8 i.e. {0, 1, 2, 3, 4, 5, 6, 7} + } +} From ee34da41ed97b131f9356260370107fd6aba3d96 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 16:38:42 +0530 Subject: [PATCH 02/13] Update largestRange.java --- Misc/largestRange.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/largestRange.java b/Misc/largestRange.java index fd61c38446d2..6877a0a600aa 100644 --- a/Misc/largestRange.java +++ b/Misc/largestRange.java @@ -1,3 +1,4 @@ +package Misc; import java.util.*; public class largestRange { From 4bee137ea6f5318f95c71b06c343a59f9309717c Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 16:40:53 +0530 Subject: [PATCH 03/13] Update largestRange.java --- Misc/largestRange.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/largestRange.java b/Misc/largestRange.java index 6877a0a600aa..7dc300450834 100644 --- a/Misc/largestRange.java +++ b/Misc/largestRange.java @@ -1,4 +1,5 @@ package Misc; + import java.util.*; public class largestRange { From 603e0100e177be498bedad122498b1e69d1d7805 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 18:24:12 +0530 Subject: [PATCH 04/13] Update largestRange.java --- Misc/largestRange.java | 84 +++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/Misc/largestRange.java b/Misc/largestRange.java index 7dc300450834..3b6a7f48ff7c 100644 --- a/Misc/largestRange.java +++ b/Misc/largestRange.java @@ -1,48 +1,48 @@ package Misc; import java.util.*; -public class largestRange -{ - // Finds the length of longest occurring consecutive numbers range in an array - public static int longestRange(int[] nums) - { - int longestRange = 0; - HashMap num = new HashMap<>(); // Stores a mapping of a number to whether the current number is part of a particular consecutive range or not - for(int x : nums) - num.put(x, true); - for(int x : nums) - { - if(!num.get(x)) - continue; - num.replace(x, false); - int currentRange=1; - int left = x - 1; - int right = x + 1; - while(num.containsKey(left)) // Search leftwards for consecutive range - { - num.replace(left, false); - currentRange+=1; - left--; - } - while(num.containsKey(right)) // Search rightwards for consecutive range - { - num.replace(right, false); - currentRange+=1; - right++; - } - if(currentRange > longestRange) // Store longest range at every interation - longestRange = currentRange; - } - return longestRange; - } - public static void main(String[] args) { - // Testcases - assert longestRange(new int[]{1, 2, 3, 4, -1, 11, 10}) == 4; - // The longest consecutive number range is of length 4 i.e. {1, 2, 3, 4} - assert longestRange(new int[]{-1, 1, 3, 5, 7})==1; - // The longest consecutive number range is of length 1 i.e. any of the element alone - assert longestRange(new int[]{0, 1, 2, 3, 4, 7, 6, 5})==8; - // The longest consecutive number range is of length 8 i.e. {0, 1, 2, 3, 4, 5, 6, 7} +public class largestRange { + + // Finds the length of longest occurring consecutive numbers range in an array + public static int longestRange(int[] nums) { + int longestRange = 0; + HashMap num = new HashMap<>(); + + /** + * Stores a mapping of a number to whether the current number is part of a particular + * consecutive range or not. + */ + for (int x : nums) num.put(x, true); + for (int x : nums) { + if (!num.get(x)) continue; + num.replace(x, false); + int currentRange = 1; + int left = x - 1; + int right = x + 1; + while (num.containsKey(left)) { // Search leftwards for consecutive range + num.replace(left, false); + currentRange += 1; + left--; + } + while (num.containsKey(right)) { // Search rightwards for consecutive range + num.replace(right, false); + currentRange += 1; + right++; + } + if (currentRange > longestRange) + longestRange = currentRange; // Store longest range at every interation } + return longestRange; + } + + public static void main(String[] args) { + // Testcases + assert longestRange(new int[] {1, 2, 3, 4, -1, 11, 10}) == 4; + // The longest consecutive number range is of length 4 i.e. {1, 2, 3, 4} + assert longestRange(new int[] {-1, 1, 3, 5, 7}) == 1; + // The longest consecutive number range is of length 1 i.e. any of the element alone + assert longestRange(new int[] {0, 1, 2, 3, 4, 7, 6, 5}) == 8; + // The longest consecutive number range is of length 8 i.e. {0, 1, 2, 3, 4, 5, 6, 7} + } } From a6f88cd038fac7b41a28d8302c87e20f10280516 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 18:27:45 +0530 Subject: [PATCH 05/13] Update largestRange.java --- Misc/largestRange.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Misc/largestRange.java b/Misc/largestRange.java index 3b6a7f48ff7c..f24e5e2438a8 100644 --- a/Misc/largestRange.java +++ b/Misc/largestRange.java @@ -1,5 +1,3 @@ -package Misc; - import java.util.*; public class largestRange { From 9e1c9637a5a68e54a6cab7fac70d7b0074491066 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 20:25:54 +0530 Subject: [PATCH 06/13] Revert "Largest range" --- Misc/largestRange.java | 46 ------------------------------------------ 1 file changed, 46 deletions(-) delete mode 100644 Misc/largestRange.java diff --git a/Misc/largestRange.java b/Misc/largestRange.java deleted file mode 100644 index f24e5e2438a8..000000000000 --- a/Misc/largestRange.java +++ /dev/null @@ -1,46 +0,0 @@ -import java.util.*; - -public class largestRange { - - // Finds the length of longest occurring consecutive numbers range in an array - public static int longestRange(int[] nums) { - int longestRange = 0; - HashMap num = new HashMap<>(); - - /** - * Stores a mapping of a number to whether the current number is part of a particular - * consecutive range or not. - */ - for (int x : nums) num.put(x, true); - for (int x : nums) { - if (!num.get(x)) continue; - num.replace(x, false); - int currentRange = 1; - int left = x - 1; - int right = x + 1; - while (num.containsKey(left)) { // Search leftwards for consecutive range - num.replace(left, false); - currentRange += 1; - left--; - } - while (num.containsKey(right)) { // Search rightwards for consecutive range - num.replace(right, false); - currentRange += 1; - right++; - } - if (currentRange > longestRange) - longestRange = currentRange; // Store longest range at every interation - } - return longestRange; - } - - public static void main(String[] args) { - // Testcases - assert longestRange(new int[] {1, 2, 3, 4, -1, 11, 10}) == 4; - // The longest consecutive number range is of length 4 i.e. {1, 2, 3, 4} - assert longestRange(new int[] {-1, 1, 3, 5, 7}) == 1; - // The longest consecutive number range is of length 1 i.e. any of the element alone - assert longestRange(new int[] {0, 1, 2, 3, 4, 7, 6, 5}) == 8; - // The longest consecutive number range is of length 8 i.e. {0, 1, 2, 3, 4, 5, 6, 7} - } -} From a382936636b8de56d0ad32d5a4a3da3c8d96e942 Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 20:57:18 +0530 Subject: [PATCH 07/13] Added WordBoggle.java --- Misc/WordBoggle.java | 130 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 Misc/WordBoggle.java diff --git a/Misc/WordBoggle.java b/Misc/WordBoggle.java new file mode 100644 index 000000000000..ea3f44ada29a --- /dev/null +++ b/Misc/WordBoggle.java @@ -0,0 +1,130 @@ +import java.util.*; + +public class wordBoggle { + + /** + * O(nm * 8^s + ws) time where n=width of boggle board, m=height of boggle board, s=length of + * longest word in string array, w= length of string array, 8 is due to 8 explorable neighbours + * O(nm + ws) space. + */ + public static List boggleBoard(char[][] board, String[] words) { + Trie trie = new Trie(); + for (String word : words) trie.add(word); + Set finalWords = new HashSet<>(); + boolean[][] visited = new boolean[board.length][board.length]; + for (int i = 0; i < board.length; i++) + for (int j = 0; j < board[i].length; j++) + explore(i, j, board, trie.root, visited, finalWords); + return new ArrayList<>(finalWords); + } + + public static void main(String[] args) { + // Testcase + List ans = + new ArrayList<>( + Arrays.asList("a", "boggle", "this", "NOTRE_PEATED", "is", "simple", "board")); + assert (boggleBoard( + new char[][] { + {'t', 'h', 'i', 's', 'i', 's', 'a'}, + {'s', 'i', 'm', 'p', 'l', 'e', 'x'}, + {'b', 'x', 'x', 'x', 'x', 'e', 'b'}, + {'x', 'o', 'g', 'g', 'l', 'x', 'o'}, + {'x', 'x', 'x', 'D', 'T', 'r', 'a'}, + {'R', 'E', 'P', 'E', 'A', 'd', 'x'}, + {'x', 'x', 'x', 'x', 'x', 'x', 'x'}, + {'N', 'O', 'T', 'R', 'E', '_', 'P'}, + {'x', 'x', 'D', 'E', 'T', 'A', 'E'}, + }, + new String[] { + "this", + "is", + "not", + "a", + "simple", + "test", + "boggle", + "board", + "REPEATED", + "NOTRE_PEATED", + }) + .equals(ans)); + } + + public static void explore( + int i, + int j, + char[][] board, + TrieNode trieNode, + boolean[][] visited, + Set finalWords) { + if (visited[i][j]) return; + + char letter = board[i][j]; + if (!trieNode.children.containsKey(letter)) { + return; + } + visited[i][j] = true; + trieNode = trieNode.children.get(letter); + if (trieNode.children.containsKey('*')) finalWords.add(trieNode.word); + + List neighbors = getNeighbors(i, j, board); + for (Integer[] neighbor : neighbors) + explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords); + + visited[i][j] = false; + } + + public static List getNeighbors(int i, int j, char[][] board) { + List neighbors = new ArrayList<>(); + if (i > 0 && j > 0) neighbors.add(new Integer[] {i - 1, j - 1}); + + if (i > 0 && j < board[0].length - 1) neighbors.add(new Integer[] {i - 1, j + 1}); + + if (i < board.length - 1 && j < board[0].length - 1) + neighbors.add(new Integer[] {i + 1, j + 1}); + + if (i < board.length - 1 && j > 0) neighbors.add(new Integer[] {i + 1, j - 1}); + + if (i > 0) neighbors.add(new Integer[] {i - 1, j}); + + if (i < board.length - 1) neighbors.add(new Integer[] {i + 1, j}); + + if (j > 0) neighbors.add(new Integer[] {i, j - 1}); + + if (j < board[0].length - 1) neighbors.add(new Integer[] {i, j + 1}); + + return neighbors; + } +} + +// Trie used to optimize string search +class TrieNode { + + Map children = new HashMap<>(); + String word = ""; +} + +class Trie { + + TrieNode root; + char endSymbol; + + public Trie() { + this.root = new TrieNode(); + this.endSymbol = '*'; + } + + public void add(String str) { + TrieNode node = this.root; + for (int i = 0; i < str.length(); i++) { + char letter = str.charAt(i); + if (!node.children.containsKey(letter)) { + TrieNode newNode = new TrieNode(); + node.children.put(letter, newNode); + } + node = node.children.get(letter); + } + node.children.put(this.endSymbol, null); + node.word = str; + } +} \ No newline at end of file From cab263ecfc7495a81402b1813f75ca1ea3404b94 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Wed, 4 Nov 2020 21:04:39 +0530 Subject: [PATCH 08/13] Update WordBoggle.java --- Misc/WordBoggle.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/WordBoggle.java b/Misc/WordBoggle.java index ea3f44ada29a..130784ac7ff4 100644 --- a/Misc/WordBoggle.java +++ b/Misc/WordBoggle.java @@ -1,6 +1,6 @@ import java.util.*; -public class wordBoggle { +public class WordBoggle { /** * O(nm * 8^s + ws) time where n=width of boggle board, m=height of boggle board, s=length of @@ -127,4 +127,4 @@ public void add(String str) { node.children.put(this.endSymbol, null); node.word = str; } -} \ No newline at end of file +} From ffbc3b1bead0cde256e91f8b613412e399db46d9 Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 21:18:02 +0530 Subject: [PATCH 09/13] Added RangeInSortedArray.java in Java/Misc --- Misc/RangeInSortedArray.java | 82 ++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Misc/RangeInSortedArray.java diff --git a/Misc/RangeInSortedArray.java b/Misc/RangeInSortedArray.java new file mode 100644 index 000000000000..65056444ff03 --- /dev/null +++ b/Misc/RangeInSortedArray.java @@ -0,0 +1,82 @@ +package Misc; + +import java.util.*; + +public class RangeInSortedArray { + + public static void main(String[] args) { + // Testcases + assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 3), new int[] {2, 4}); + assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 4), new int[] {5, 5}); + assert Arrays.equals(sortedRange(new int[] {0, 1, 2}, 3), new int[] {-1, -1}); + } + + // Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums' + // Gives [-1, -1] in case element doesn't exist in array + public static int[] sortedRange(int[] nums, int key) { + int[] range = new int[] {-1, -1}; + alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true); + alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false); + return range; + } + + // Recursive altered binary search which searches for leftmost as well as rightmost occurrence of + // 'key' + public static void alteredBinSearch( + int[] nums, int key, int left, int right, int[] range, boolean goLeft) { + if (left > right) return; + int mid = (left + right) / 2; + if (nums[mid] > key) alteredBinSearch(nums, key, left, mid - 1, range, goLeft); + else if (nums[mid] < key) alteredBinSearch(nums, key, mid + 1, right, range, goLeft); + else { + if (goLeft) { + if (mid == 0 || nums[mid - 1] != key) range[0] = mid; + else alteredBinSearch(nums, key, left, mid - 1, range, goLeft); + } else { + if (mid == nums.length - 1 || nums[mid + 1] != key) range[1] = mid; + else alteredBinSearch(nums, key, mid + 1, right, range, goLeft); + } + } + } + + // Iterative altered binary search which searches for leftmost as well as rightmost occurrence of + // 'key' + public static void alteredBinSearchIter( + int[] nums, int key, int left, int right, int[] range, boolean goLeft) { + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] > key) right = mid - 1; + else if (nums[mid] < key) left = mid + 1; + else { + if (goLeft) { + if (mid == 0 || nums[mid - 1] != key) { + range[0] = mid; + return; + } else right = mid - 1; + } else { + if (mid == nums.length - 1 || nums[mid + 1] != key) { + range[1] = mid; + return; + } else left = mid + 1; + } + } + } + } + + public static int getCountLessThan(int[] nums, int key) { + return getLessThan(nums, key, 0, nums.length - 1); + } + + public static int getLessThan(int[] nums, int key, int left, int right) { + int count = 0; + while (left <= right) { + int mid = (left + right) / 2; + if (nums[mid] > key) right = mid - 1; + else if (nums[mid] <= key) { + count = mid + 1; // Atleast mid+1 elements exist which are <= key + left = mid + 1; + } + } + return count; + } +} \ No newline at end of file From 3a6ad5c7eb2395c9e7363f2654c84b7bf83efbf3 Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 22:51:27 +0530 Subject: [PATCH 10/13] Added MinSubstrContainingChars.java in Java/strings --- strings/MinSubstrContainingChars.java | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 strings/MinSubstrContainingChars.java diff --git a/strings/MinSubstrContainingChars.java b/strings/MinSubstrContainingChars.java new file mode 100644 index 000000000000..4ffe4c0c0e43 --- /dev/null +++ b/strings/MinSubstrContainingChars.java @@ -0,0 +1,87 @@ +package strings; + +import java.util.*; + +public class MinSubstrContainingChars { + + public static void main(String[] args) { + // Testcases + assert smallestSubstrContaining("workforcode", "wfc").equals("workforc"); + assert smallestSubstrContaining("abcdeklmhactr", "abcl").equals("abcdekl"); + assert smallestSubstrContaining("SachinTendulkar", "SrT").equals("SachinTendulkar"); + } + + // Find the smallest length substring of a string containing all the characters in smaller string + public static String smallestSubstrContaining(String bigString, String smallString) { + HashMap targetCharCounts = getCharCounts(smallString); + int[] substrBounds = getSubstringBounds(bigString, targetCharCounts); + return getStringFromBounds(bigString, substrBounds); + } + + // Builds HashMap of characters to its counts + public static HashMap getCharCounts(String str) { + HashMap charCounts = new HashMap<>(); + for (char x : str.toCharArray()) { + increaseCharCount(x, charCounts); + } + return charCounts; + } + + // Increase occurrence count of character x in hashmap + public static void increaseCharCount(Character x, HashMap charCounts) { + charCounts.put(x, charCounts.getOrDefault(x, 0) + 1); + } + + // Decrease occurrence count of character x in hashmap + public static void decreaseCharCount(char x, HashMap charCounts) { + charCounts.put(x, charCounts.get(x) - 1); + } + + // Gets the bounds of substring occurrence + public static int[] getSubstringBounds(String str, HashMap charCounts) { + int[] substrBounds = new int[] {0, (int) Double.POSITIVE_INFINITY}; + HashMap substrCharCounts = new HashMap<>(); + int numUniqueChars = charCounts.size(); + int numUniqueCharsDone = 0; + int left = 0, right = 0; + while (right < str.length()) { + char rightChar = str.charAt(right); + if (!charCounts.containsKey(rightChar)) { + right++; + continue; + } + increaseCharCount(rightChar, substrCharCounts); + if (substrCharCounts.get(rightChar).equals(charCounts.get(rightChar))) numUniqueCharsDone++; + while (numUniqueCharsDone == numUniqueChars && left <= right) { + substrBounds = getCloserBounds(left, right, substrBounds[0], substrBounds[1]); + char leftChar = str.charAt(left); + if (!charCounts.containsKey(leftChar)) { + left++; + continue; + } + if (substrCharCounts.get(leftChar).equals(charCounts.get(leftChar))) numUniqueCharsDone--; + decreaseCharCount(leftChar, substrCharCounts); + left++; + } + right++; + } + + // System.out.println((int)Double.POSITIVE_INFINITY+" "+Arrays.toString(substrBounds)); + return substrBounds; + } + + // Find the closer bound out of (index1, index2) and (index3, index4) + + public static int[] getCloserBounds(int index1, int index2, int index3, int index4) { + return (index2 - index1 < index4 - index3) + ? new int[] {index1, index2} + : new int[] {index3, index4}; + } + + // Split string into substring starting from bounds[0] and ending at bounds[1] + public static String getStringFromBounds(String str, int[] bounds) { + int start = bounds[0], end = bounds[1]; + if (end == (int) Double.POSITIVE_INFINITY) return ""; + return str.substring(start, end + 1); + } +} \ No newline at end of file From e72d622aaf15ae7317e8f6959353aceda4234d4c Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 23:23:23 +0530 Subject: [PATCH 11/13] Added new Java file LongestSubstringWithoutDuplication.java --- .../LongestSubstringWithoutDuplication.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 strings/LongestSubstringWithoutDuplication.java diff --git a/strings/LongestSubstringWithoutDuplication.java b/strings/LongestSubstringWithoutDuplication.java new file mode 100644 index 000000000000..0476dcca28b6 --- /dev/null +++ b/strings/LongestSubstringWithoutDuplication.java @@ -0,0 +1,28 @@ +import java.util.*; + +public class LongestSubstringWithoutDuplication { + + public static void main(String[] args) { + // Testcases + assert longestUniqueSubstring("lmnoppqrrsss").equals("lmnop"); + assert longestUniqueSubstring("falafel").equals("lafe"); + assert longestUniqueSubstring("krishnamachari").equals("krishnam"); + } + + // Finds the longest substring of a string having unique characters + public static String longestUniqueSubstring(String str) { + if (str.equals("")) return ""; + HashMap lastSeenAt = new HashMap<>(); + int[] longest = new int[] { 0, 1 }; + int start = 0; + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (lastSeenAt.containsKey(c)) start = + Math.max(start, lastSeenAt.get(c) + 1); + if (longest[1] - longest[0] < i + 1 - start) longest = + new int[] { start, i + 1 }; + lastSeenAt.put(c, i); + } + return str.substring(longest[0], longest[1]); + } +} From bf0c6f9edffa329dff3191bcd0e405b4e5c63a43 Mon Sep 17 00:00:00 2001 From: Azad Date: Thu, 5 Nov 2020 00:58:30 +0530 Subject: [PATCH 12/13] Added GenerateBalancedParenthesis.java --- Misc/GenerateBalancedParenthesis.java | 66 +++++++++ Misc/RangeInSortedArray.java | 82 ----------- Misc/WordBoggle.java | 130 ------------------ .../LongestSubstringWithoutDuplication.java | 28 ---- strings/MinSubstrContainingChars.java | 87 ------------ 5 files changed, 66 insertions(+), 327 deletions(-) create mode 100644 Misc/GenerateBalancedParenthesis.java delete mode 100644 Misc/RangeInSortedArray.java delete mode 100644 Misc/WordBoggle.java delete mode 100644 strings/LongestSubstringWithoutDuplication.java delete mode 100644 strings/MinSubstrContainingChars.java diff --git a/Misc/GenerateBalancedParenthesis.java b/Misc/GenerateBalancedParenthesis.java new file mode 100644 index 000000000000..e9f4c63668a9 --- /dev/null +++ b/Misc/GenerateBalancedParenthesis.java @@ -0,0 +1,66 @@ +package Misc; + +import java.util.*; + +class ParenthesisString { + + String str; + int openCount, closedCount; // Open & Closed Parenthesis count respectively + + public ParenthesisString(String str, int openCount, int closedCount) { + this.str = str; + this.openCount = openCount; + this.closedCount = closedCount; + } +} + +public class generateBalancedParenthesis { + + /** + * Follows a BFS-based approach to generate all combinations of balanced paranthesis with 'A' + * number of pairs Time complexity : O(4^n/sqrt(n)) Refer this : + * https://en.wikipedia.org/wiki/Central_binomial_coefficient Space complexity : O(n*2^n) + */ + public static List generateParenthesis(int A) { + List res = new ArrayList<>(); + Queue queue = new ArrayDeque<>(); + queue.add(new ParenthesisString("", 0, 0)); + while (!queue.isEmpty()) { + ParenthesisString ps = queue.poll(); + // Add to the result if the max open & closed parenthesis count is reached + if (ps.openCount == A && ps.closedCount == A) res.add(ps.str); + else { + if (ps.openCount < A) + queue.add( // Add if we can add an open parenthesis + new ParenthesisString(ps.str + "(", ps.openCount + 1, ps.closedCount)); + + if (ps.openCount > ps.closedCount) + queue.add( // Add if we can add a closed parenthesis + new ParenthesisString(ps.str + ")", ps.openCount, ps.closedCount + 1)); + } + } + return res; + } + + public static void main(String[] args) { + // Testcases + assert generateParenthesis(4) + .equals( + Arrays.asList( + "(((())))", + "((()()))", + "((())())", + "((()))()", + "(()(()))", + "(()()())", + "(()())()", + "(())(())", + "(())()()", + "()((()))", + "()(()())", + "()(())()", + "()()(())", + "()()()()")); + assert generateParenthesis(2).equals(Arrays.asList("(())", "()()")); + } +} \ No newline at end of file diff --git a/Misc/RangeInSortedArray.java b/Misc/RangeInSortedArray.java deleted file mode 100644 index 65056444ff03..000000000000 --- a/Misc/RangeInSortedArray.java +++ /dev/null @@ -1,82 +0,0 @@ -package Misc; - -import java.util.*; - -public class RangeInSortedArray { - - public static void main(String[] args) { - // Testcases - assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 3), new int[] {2, 4}); - assert Arrays.equals(sortedRange(new int[] {1, 2, 3, 3, 3, 4, 5}, 4), new int[] {5, 5}); - assert Arrays.equals(sortedRange(new int[] {0, 1, 2}, 3), new int[] {-1, -1}); - } - - // Get the 1st and last occurrence index of a number 'key' in a non-decreasing array 'nums' - // Gives [-1, -1] in case element doesn't exist in array - public static int[] sortedRange(int[] nums, int key) { - int[] range = new int[] {-1, -1}; - alteredBinSearchIter(nums, key, 0, nums.length - 1, range, true); - alteredBinSearchIter(nums, key, 0, nums.length - 1, range, false); - return range; - } - - // Recursive altered binary search which searches for leftmost as well as rightmost occurrence of - // 'key' - public static void alteredBinSearch( - int[] nums, int key, int left, int right, int[] range, boolean goLeft) { - if (left > right) return; - int mid = (left + right) / 2; - if (nums[mid] > key) alteredBinSearch(nums, key, left, mid - 1, range, goLeft); - else if (nums[mid] < key) alteredBinSearch(nums, key, mid + 1, right, range, goLeft); - else { - if (goLeft) { - if (mid == 0 || nums[mid - 1] != key) range[0] = mid; - else alteredBinSearch(nums, key, left, mid - 1, range, goLeft); - } else { - if (mid == nums.length - 1 || nums[mid + 1] != key) range[1] = mid; - else alteredBinSearch(nums, key, mid + 1, right, range, goLeft); - } - } - } - - // Iterative altered binary search which searches for leftmost as well as rightmost occurrence of - // 'key' - public static void alteredBinSearchIter( - int[] nums, int key, int left, int right, int[] range, boolean goLeft) { - while (left <= right) { - int mid = (left + right) / 2; - if (nums[mid] > key) right = mid - 1; - else if (nums[mid] < key) left = mid + 1; - else { - if (goLeft) { - if (mid == 0 || nums[mid - 1] != key) { - range[0] = mid; - return; - } else right = mid - 1; - } else { - if (mid == nums.length - 1 || nums[mid + 1] != key) { - range[1] = mid; - return; - } else left = mid + 1; - } - } - } - } - - public static int getCountLessThan(int[] nums, int key) { - return getLessThan(nums, key, 0, nums.length - 1); - } - - public static int getLessThan(int[] nums, int key, int left, int right) { - int count = 0; - while (left <= right) { - int mid = (left + right) / 2; - if (nums[mid] > key) right = mid - 1; - else if (nums[mid] <= key) { - count = mid + 1; // Atleast mid+1 elements exist which are <= key - left = mid + 1; - } - } - return count; - } -} \ No newline at end of file diff --git a/Misc/WordBoggle.java b/Misc/WordBoggle.java deleted file mode 100644 index 130784ac7ff4..000000000000 --- a/Misc/WordBoggle.java +++ /dev/null @@ -1,130 +0,0 @@ -import java.util.*; - -public class WordBoggle { - - /** - * O(nm * 8^s + ws) time where n=width of boggle board, m=height of boggle board, s=length of - * longest word in string array, w= length of string array, 8 is due to 8 explorable neighbours - * O(nm + ws) space. - */ - public static List boggleBoard(char[][] board, String[] words) { - Trie trie = new Trie(); - for (String word : words) trie.add(word); - Set finalWords = new HashSet<>(); - boolean[][] visited = new boolean[board.length][board.length]; - for (int i = 0; i < board.length; i++) - for (int j = 0; j < board[i].length; j++) - explore(i, j, board, trie.root, visited, finalWords); - return new ArrayList<>(finalWords); - } - - public static void main(String[] args) { - // Testcase - List ans = - new ArrayList<>( - Arrays.asList("a", "boggle", "this", "NOTRE_PEATED", "is", "simple", "board")); - assert (boggleBoard( - new char[][] { - {'t', 'h', 'i', 's', 'i', 's', 'a'}, - {'s', 'i', 'm', 'p', 'l', 'e', 'x'}, - {'b', 'x', 'x', 'x', 'x', 'e', 'b'}, - {'x', 'o', 'g', 'g', 'l', 'x', 'o'}, - {'x', 'x', 'x', 'D', 'T', 'r', 'a'}, - {'R', 'E', 'P', 'E', 'A', 'd', 'x'}, - {'x', 'x', 'x', 'x', 'x', 'x', 'x'}, - {'N', 'O', 'T', 'R', 'E', '_', 'P'}, - {'x', 'x', 'D', 'E', 'T', 'A', 'E'}, - }, - new String[] { - "this", - "is", - "not", - "a", - "simple", - "test", - "boggle", - "board", - "REPEATED", - "NOTRE_PEATED", - }) - .equals(ans)); - } - - public static void explore( - int i, - int j, - char[][] board, - TrieNode trieNode, - boolean[][] visited, - Set finalWords) { - if (visited[i][j]) return; - - char letter = board[i][j]; - if (!trieNode.children.containsKey(letter)) { - return; - } - visited[i][j] = true; - trieNode = trieNode.children.get(letter); - if (trieNode.children.containsKey('*')) finalWords.add(trieNode.word); - - List neighbors = getNeighbors(i, j, board); - for (Integer[] neighbor : neighbors) - explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords); - - visited[i][j] = false; - } - - public static List getNeighbors(int i, int j, char[][] board) { - List neighbors = new ArrayList<>(); - if (i > 0 && j > 0) neighbors.add(new Integer[] {i - 1, j - 1}); - - if (i > 0 && j < board[0].length - 1) neighbors.add(new Integer[] {i - 1, j + 1}); - - if (i < board.length - 1 && j < board[0].length - 1) - neighbors.add(new Integer[] {i + 1, j + 1}); - - if (i < board.length - 1 && j > 0) neighbors.add(new Integer[] {i + 1, j - 1}); - - if (i > 0) neighbors.add(new Integer[] {i - 1, j}); - - if (i < board.length - 1) neighbors.add(new Integer[] {i + 1, j}); - - if (j > 0) neighbors.add(new Integer[] {i, j - 1}); - - if (j < board[0].length - 1) neighbors.add(new Integer[] {i, j + 1}); - - return neighbors; - } -} - -// Trie used to optimize string search -class TrieNode { - - Map children = new HashMap<>(); - String word = ""; -} - -class Trie { - - TrieNode root; - char endSymbol; - - public Trie() { - this.root = new TrieNode(); - this.endSymbol = '*'; - } - - public void add(String str) { - TrieNode node = this.root; - for (int i = 0; i < str.length(); i++) { - char letter = str.charAt(i); - if (!node.children.containsKey(letter)) { - TrieNode newNode = new TrieNode(); - node.children.put(letter, newNode); - } - node = node.children.get(letter); - } - node.children.put(this.endSymbol, null); - node.word = str; - } -} diff --git a/strings/LongestSubstringWithoutDuplication.java b/strings/LongestSubstringWithoutDuplication.java deleted file mode 100644 index 0476dcca28b6..000000000000 --- a/strings/LongestSubstringWithoutDuplication.java +++ /dev/null @@ -1,28 +0,0 @@ -import java.util.*; - -public class LongestSubstringWithoutDuplication { - - public static void main(String[] args) { - // Testcases - assert longestUniqueSubstring("lmnoppqrrsss").equals("lmnop"); - assert longestUniqueSubstring("falafel").equals("lafe"); - assert longestUniqueSubstring("krishnamachari").equals("krishnam"); - } - - // Finds the longest substring of a string having unique characters - public static String longestUniqueSubstring(String str) { - if (str.equals("")) return ""; - HashMap lastSeenAt = new HashMap<>(); - int[] longest = new int[] { 0, 1 }; - int start = 0; - for (int i = 0; i < str.length(); i++) { - char c = str.charAt(i); - if (lastSeenAt.containsKey(c)) start = - Math.max(start, lastSeenAt.get(c) + 1); - if (longest[1] - longest[0] < i + 1 - start) longest = - new int[] { start, i + 1 }; - lastSeenAt.put(c, i); - } - return str.substring(longest[0], longest[1]); - } -} diff --git a/strings/MinSubstrContainingChars.java b/strings/MinSubstrContainingChars.java deleted file mode 100644 index 4ffe4c0c0e43..000000000000 --- a/strings/MinSubstrContainingChars.java +++ /dev/null @@ -1,87 +0,0 @@ -package strings; - -import java.util.*; - -public class MinSubstrContainingChars { - - public static void main(String[] args) { - // Testcases - assert smallestSubstrContaining("workforcode", "wfc").equals("workforc"); - assert smallestSubstrContaining("abcdeklmhactr", "abcl").equals("abcdekl"); - assert smallestSubstrContaining("SachinTendulkar", "SrT").equals("SachinTendulkar"); - } - - // Find the smallest length substring of a string containing all the characters in smaller string - public static String smallestSubstrContaining(String bigString, String smallString) { - HashMap targetCharCounts = getCharCounts(smallString); - int[] substrBounds = getSubstringBounds(bigString, targetCharCounts); - return getStringFromBounds(bigString, substrBounds); - } - - // Builds HashMap of characters to its counts - public static HashMap getCharCounts(String str) { - HashMap charCounts = new HashMap<>(); - for (char x : str.toCharArray()) { - increaseCharCount(x, charCounts); - } - return charCounts; - } - - // Increase occurrence count of character x in hashmap - public static void increaseCharCount(Character x, HashMap charCounts) { - charCounts.put(x, charCounts.getOrDefault(x, 0) + 1); - } - - // Decrease occurrence count of character x in hashmap - public static void decreaseCharCount(char x, HashMap charCounts) { - charCounts.put(x, charCounts.get(x) - 1); - } - - // Gets the bounds of substring occurrence - public static int[] getSubstringBounds(String str, HashMap charCounts) { - int[] substrBounds = new int[] {0, (int) Double.POSITIVE_INFINITY}; - HashMap substrCharCounts = new HashMap<>(); - int numUniqueChars = charCounts.size(); - int numUniqueCharsDone = 0; - int left = 0, right = 0; - while (right < str.length()) { - char rightChar = str.charAt(right); - if (!charCounts.containsKey(rightChar)) { - right++; - continue; - } - increaseCharCount(rightChar, substrCharCounts); - if (substrCharCounts.get(rightChar).equals(charCounts.get(rightChar))) numUniqueCharsDone++; - while (numUniqueCharsDone == numUniqueChars && left <= right) { - substrBounds = getCloserBounds(left, right, substrBounds[0], substrBounds[1]); - char leftChar = str.charAt(left); - if (!charCounts.containsKey(leftChar)) { - left++; - continue; - } - if (substrCharCounts.get(leftChar).equals(charCounts.get(leftChar))) numUniqueCharsDone--; - decreaseCharCount(leftChar, substrCharCounts); - left++; - } - right++; - } - - // System.out.println((int)Double.POSITIVE_INFINITY+" "+Arrays.toString(substrBounds)); - return substrBounds; - } - - // Find the closer bound out of (index1, index2) and (index3, index4) - - public static int[] getCloserBounds(int index1, int index2, int index3, int index4) { - return (index2 - index1 < index4 - index3) - ? new int[] {index1, index2} - : new int[] {index3, index4}; - } - - // Split string into substring starting from bounds[0] and ending at bounds[1] - public static String getStringFromBounds(String str, int[] bounds) { - int start = bounds[0], end = bounds[1]; - if (end == (int) Double.POSITIVE_INFINITY) return ""; - return str.substring(start, end + 1); - } -} \ No newline at end of file From 2ac07393656b52959399742187b5657cd5808790 Mon Sep 17 00:00:00 2001 From: Azad Nautiyal Date: Thu, 5 Nov 2020 01:21:21 +0530 Subject: [PATCH 13/13] Update GenerateBalancedParenthesis.java --- Misc/GenerateBalancedParenthesis.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/GenerateBalancedParenthesis.java b/Misc/GenerateBalancedParenthesis.java index e9f4c63668a9..f8f602fa1f60 100644 --- a/Misc/GenerateBalancedParenthesis.java +++ b/Misc/GenerateBalancedParenthesis.java @@ -14,7 +14,7 @@ public ParenthesisString(String str, int openCount, int closedCount) { } } -public class generateBalancedParenthesis { +public class GenerateBalancedParenthesis { /** * Follows a BFS-based approach to generate all combinations of balanced paranthesis with 'A' @@ -63,4 +63,4 @@ assert generateParenthesis(4) "()()()()")); assert generateParenthesis(2).equals(Arrays.asList("(())", "()()")); } -} \ No newline at end of file +}