From 0172c299c7cb3394ff8700c71c2cc00d24451994 Mon Sep 17 00:00:00 2001 From: Azad Date: Wed, 4 Nov 2020 16:28:51 +0530 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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/15] 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 5adb4fc1f25ac28b1e418ff4773216ee004e47fc Mon Sep 17 00:00:00 2001 From: Azad Date: Thu, 5 Nov 2020 01:11:17 +0530 Subject: [PATCH 13/15] Added New File HappyNumber.java in Java/Maths --- Maths/HappyNumber.java | 30 ++++++++++++ Misc/GenerateBalancedParenthesis.java | 66 --------------------------- 2 files changed, 30 insertions(+), 66 deletions(-) create mode 100644 Maths/HappyNumber.java delete mode 100644 Misc/GenerateBalancedParenthesis.java diff --git a/Maths/HappyNumber.java b/Maths/HappyNumber.java new file mode 100644 index 000000000000..a1a3210617cd --- /dev/null +++ b/Maths/HappyNumber.java @@ -0,0 +1,30 @@ +package Maths; + +public class HappyNumber { + + // Check if a number is happy or not. Refer : https://mathworld.wolfram.com/HappyNumber.html + public static boolean isHappy(int num) { + int slow = num, fast = num; + do { + slow = digitSquareSum(slow); // Move one step + fast = digitSquareSum(digitSquareSum(fast)); // Move 2 steps + } while (slow != fast); + return slow == 1; // See if the cycle is stuck on number 1 + } + + public static int digitSquareSum(int num) { + int sum = 0, digit; + while (num > 0) { + digit = num % 10; + sum += digit * digit; + num /= 10; + } + return sum; + } + + public static void main(String[] args) { + // Testcases + assert isHappy(23); + assert !isHappy(11); + } +} \ No newline at end of file diff --git a/Misc/GenerateBalancedParenthesis.java b/Misc/GenerateBalancedParenthesis.java deleted file mode 100644 index e9f4c63668a9..000000000000 --- a/Misc/GenerateBalancedParenthesis.java +++ /dev/null @@ -1,66 +0,0 @@ -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 From 4819b5522fe9ef7275bb3cce095b284218ca81f4 Mon Sep 17 00:00:00 2001 From: Azad Date: Thu, 5 Nov 2020 01:19:24 +0530 Subject: [PATCH 14/15] Added Manacher's Algorithm's implementation --- Maths/HappyNumber.java | 30 ------- .../LongestPalindromicSubstringManacher.java | 83 +++++++++++++++++++ 2 files changed, 83 insertions(+), 30 deletions(-) delete mode 100644 Maths/HappyNumber.java create mode 100644 strings/LongestPalindromicSubstringManacher.java diff --git a/Maths/HappyNumber.java b/Maths/HappyNumber.java deleted file mode 100644 index a1a3210617cd..000000000000 --- a/Maths/HappyNumber.java +++ /dev/null @@ -1,30 +0,0 @@ -package Maths; - -public class HappyNumber { - - // Check if a number is happy or not. Refer : https://mathworld.wolfram.com/HappyNumber.html - public static boolean isHappy(int num) { - int slow = num, fast = num; - do { - slow = digitSquareSum(slow); // Move one step - fast = digitSquareSum(digitSquareSum(fast)); // Move 2 steps - } while (slow != fast); - return slow == 1; // See if the cycle is stuck on number 1 - } - - public static int digitSquareSum(int num) { - int sum = 0, digit; - while (num > 0) { - digit = num % 10; - sum += digit * digit; - num /= 10; - } - return sum; - } - - public static void main(String[] args) { - // Testcases - assert isHappy(23); - assert !isHappy(11); - } -} \ No newline at end of file diff --git a/strings/LongestPalindromicSubstringManacher.java b/strings/LongestPalindromicSubstringManacher.java new file mode 100644 index 000000000000..ed79d6a750e5 --- /dev/null +++ b/strings/LongestPalindromicSubstringManacher.java @@ -0,0 +1,83 @@ +package strings; + +import java.util.*; + +public class longestPalindromicSubstringManacher { + + // Finds the longest palindromic substring in a string s in O(n) time using Manacher's algorithm. + // An explanation of Manacher's algorithm can be found here : + // https://cp-algorithms.com/string/manacher.html + public static String findLongestPalindrome(String s) { + if (s == null || s.length() == 0) return ""; + + char[] s2 = addBoundaries(s.toCharArray()); + int[] p = new int[s2.length]; + int c = 0, r = 0; // Here the first element in s2 has been processed. + int m = 0, n = 0; // The walking indices to compare if two elements are the same. + for (int i = 1; i < s2.length; i++) { + if (i > r) { + p[i] = 0; + m = i - 1; + n = i + 1; + } else { + int i2 = c * 2 - i; + if (p[i2] < (r - i - 1)) { + p[i] = p[i2]; + m = -1; // This signals bypassing the while loop below. + } else { + p[i] = r - i - 1; + n = r; + m = i * 2 - n; + } + } + while (m >= 0 && n < s2.length && s2[m] == s2[n]) { + p[i]++; + m--; + n++; + } + if ((i + p[i]) > r) { + c = i; + r = i + p[i]; + } + } + int len = 0; + c = 0; + for (int i = 1; i < s2.length; i++) { + if (len < p[i]) { + len = p[i]; + c = i; + } + } + char[] ss = Arrays.copyOfRange(s2, c - len, c + len + 1); + return String.valueOf(removeBoundaries(ss)); + } + + private static char[] addBoundaries(char[] cs) { + if (cs == null || cs.length == 0) return "||".toCharArray(); + + char[] cs2 = new char[cs.length * 2 + 1]; + for (int i = 0; i < (cs2.length - 1); i = i + 2) { + cs2[i] = '|'; + cs2[i + 1] = cs[i / 2]; + } + cs2[cs2.length - 1] = '|'; + return cs2; + } + + private static char[] removeBoundaries(char[] cs) { + if (cs == null || cs.length < 3) return "".toCharArray(); + + char[] cs2 = new char[(cs.length - 1) / 2]; + for (int i = 0; i < cs2.length; i++) { + cs2[i] = cs[i * 2 + 1]; + } + return cs2; + } + + public static void main(String[] args) { + // Testcases + assert findLongestPalindrome("abcabcabba").equals("abba"); + assert findLongestPalindrome("abcde").equals("a"); + assert findLongestPalindrome("banana").equals("anana"); + } +} \ No newline at end of file From 76600269eaf0aee67d63d0cab5cdf1d441fa09fc Mon Sep 17 00:00:00 2001 From: Azad Date: Thu, 5 Nov 2020 01:31:31 +0530 Subject: [PATCH 15/15] Added TopoSortKahn.java to Java/Misc --- Misc/TopoSortKahn.java | 112 ++++++++++++++++++ .../LongestPalindromicSubstringManacher.java | 83 ------------- 2 files changed, 112 insertions(+), 83 deletions(-) create mode 100644 Misc/TopoSortKahn.java delete mode 100644 strings/LongestPalindromicSubstringManacher.java diff --git a/Misc/TopoSortKahn.java b/Misc/TopoSortKahn.java new file mode 100644 index 000000000000..5d061333c08b --- /dev/null +++ b/Misc/TopoSortKahn.java @@ -0,0 +1,112 @@ +package Misc; + +import java.util.*; + +class jobGraph2 { + + ArrayList nodes; + // ArrayList jobs; + HashMap graph = new HashMap<>(); + + // A graph with nodes as jobs and edges as dependencies + + jobGraph2(ArrayList jobs) { + // this.jobs=jobs; + this.nodes = new ArrayList<>(); + for (int job : jobs) this.addNode(job); + } + + void addDep(int job, int dep) { + jobNode2 j = this.getNode(job); + jobNode2 depNode = this.getNode(dep); + j.deps.add(depNode); + depNode.prereqCount++; + } + + void addNode(int job) { + this.graph.put(job, new jobNode2(job)); + nodes.add(graph.get(job)); + } + + jobNode2 getNode(int job) { + if (!graph.containsKey(job)) addNode(job); + return graph.get(job); + } +} + +// Nodes of a job-graph consisting of the job and its number of pre-requisites +class jobNode2 { + + int job, prereqCount; + ArrayList deps; + + jobNode2(int job) { + this.job = job; + this.deps = new ArrayList<>(); + this.prereqCount = 0; + } +} + +public class TopoSortKahn { + + // Gives the topological ordering given a set of jobs and their prerequisites + public static ArrayList topoSort(ArrayList jobs, ArrayList deps) { + jobGraph2 graph = createJobGraph(jobs, deps); + return getOrderedJobs(graph); + } + + // Forms the job graph using given list of ordered pairs of dependencies and job list + public static jobGraph2 createJobGraph(ArrayList jobs, ArrayList deps) { + jobGraph2 j = new jobGraph2(jobs); + for (Integer[] t : deps) j.addDep(t[0], t[1]); + return j; + } + + // Builds the Topological sort using Kahn's Algorithm + public static ArrayList getOrderedJobs(jobGraph2 graph) { + ArrayList orderedJobs = new ArrayList<>(); + ArrayList nodesWithNoPrereqs = new ArrayList<>(); + for (jobNode2 x : graph.nodes) { + if (x.prereqCount == 0) nodesWithNoPrereqs.add(x); + } + while (nodesWithNoPrereqs.size() != 0) { + jobNode2 temp = nodesWithNoPrereqs.remove(nodesWithNoPrereqs.size() - 1); + orderedJobs.add(temp.job); + removeDeps(temp, nodesWithNoPrereqs); + } + boolean graphHasEdges = false; + for (jobNode2 t : graph.nodes) { + if (t.prereqCount != 0) { + graphHasEdges = true; + break; + } + } + return graphHasEdges ? new ArrayList<>() : orderedJobs; + } + + // Removes Dependencies of node currently being explored + public static void removeDeps(jobNode2 node, ArrayList nodesWithNoprereqs) { + while (node.deps.size() != 0) { + jobNode2 dep = node.deps.remove(node.deps.size() - 1); + dep.prereqCount--; + if (dep.prereqCount == 0) nodesWithNoprereqs.add(dep); + } + } + + public static void main(String[] args) { + // Sample Testcase + ArrayList jobs = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7)); + ArrayList deps = new ArrayList<>(); + deps.add( + new Integer[] { + 2, 3 + }); // (2, 3) indicates that job 2 has to be completed before starting job 3 + deps.add(new Integer[] {2, 5}); + deps.add(new Integer[] {1, 3}); + deps.add(new Integer[] {3, 4}); + deps.add(new Integer[] {4, 6}); + deps.add(new Integer[] {5, 6}); + deps.add(new Integer[] {6, 7}); + assert topoSort(jobs, deps).equals(Arrays.asList(2, 5, 1, 3, 4, 6, 7)); + } +} \ No newline at end of file diff --git a/strings/LongestPalindromicSubstringManacher.java b/strings/LongestPalindromicSubstringManacher.java deleted file mode 100644 index ed79d6a750e5..000000000000 --- a/strings/LongestPalindromicSubstringManacher.java +++ /dev/null @@ -1,83 +0,0 @@ -package strings; - -import java.util.*; - -public class longestPalindromicSubstringManacher { - - // Finds the longest palindromic substring in a string s in O(n) time using Manacher's algorithm. - // An explanation of Manacher's algorithm can be found here : - // https://cp-algorithms.com/string/manacher.html - public static String findLongestPalindrome(String s) { - if (s == null || s.length() == 0) return ""; - - char[] s2 = addBoundaries(s.toCharArray()); - int[] p = new int[s2.length]; - int c = 0, r = 0; // Here the first element in s2 has been processed. - int m = 0, n = 0; // The walking indices to compare if two elements are the same. - for (int i = 1; i < s2.length; i++) { - if (i > r) { - p[i] = 0; - m = i - 1; - n = i + 1; - } else { - int i2 = c * 2 - i; - if (p[i2] < (r - i - 1)) { - p[i] = p[i2]; - m = -1; // This signals bypassing the while loop below. - } else { - p[i] = r - i - 1; - n = r; - m = i * 2 - n; - } - } - while (m >= 0 && n < s2.length && s2[m] == s2[n]) { - p[i]++; - m--; - n++; - } - if ((i + p[i]) > r) { - c = i; - r = i + p[i]; - } - } - int len = 0; - c = 0; - for (int i = 1; i < s2.length; i++) { - if (len < p[i]) { - len = p[i]; - c = i; - } - } - char[] ss = Arrays.copyOfRange(s2, c - len, c + len + 1); - return String.valueOf(removeBoundaries(ss)); - } - - private static char[] addBoundaries(char[] cs) { - if (cs == null || cs.length == 0) return "||".toCharArray(); - - char[] cs2 = new char[cs.length * 2 + 1]; - for (int i = 0; i < (cs2.length - 1); i = i + 2) { - cs2[i] = '|'; - cs2[i + 1] = cs[i / 2]; - } - cs2[cs2.length - 1] = '|'; - return cs2; - } - - private static char[] removeBoundaries(char[] cs) { - if (cs == null || cs.length < 3) return "".toCharArray(); - - char[] cs2 = new char[(cs.length - 1) / 2]; - for (int i = 0; i < cs2.length; i++) { - cs2[i] = cs[i * 2 + 1]; - } - return cs2; - } - - public static void main(String[] args) { - // Testcases - assert findLongestPalindrome("abcabcabba").equals("abba"); - assert findLongestPalindrome("abcde").equals("a"); - assert findLongestPalindrome("banana").equals("anana"); - } -} \ No newline at end of file