diff --git a/Misc/RangeInSortedArray.java b/Misc/RangeInSortedArray.java index 65056444f..5e0563bc2 100644 --- a/Misc/RangeInSortedArray.java +++ b/Misc/RangeInSortedArray.java @@ -4,79 +4,79 @@ 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}); - } + 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; - } + // 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); - } + // 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; } + } } + } - // 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 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; + } } - - 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 + return count; + } +} diff --git a/Misc/WordBoggle.java b/Misc/WordBoggle.java index 130784ac7..e7f926423 100644 --- a/Misc/WordBoggle.java +++ b/Misc/WordBoggle.java @@ -2,129 +2,129 @@ 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); + /** + * 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); - 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)); - } + List neighbors = getNeighbors(i, j, board); + for (Integer[] neighbor : neighbors) + explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords); - public static void explore( - int i, - int j, - char[][] board, - TrieNode trieNode, - boolean[][] visited, - Set finalWords) { - if (visited[i][j]) return; + visited[i][j] = false; + } - 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); + 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}); - List neighbors = getNeighbors(i, j, board); - for (Integer[] neighbor : neighbors) - explore(neighbor[0], neighbor[1], board, trieNode, visited, finalWords); + if (i > 0 && j < board[0].length - 1) neighbors.add(new Integer[] {i - 1, j + 1}); - visited[i][j] = false; - } + if (i < board.length - 1 && j < board[0].length - 1) + neighbors.add(new Integer[] {i + 1, j + 1}); - 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 < board.length - 1 && 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 > 0) neighbors.add(new Integer[] {i - 1, j}); - if (i < board.length - 1 && j < board[0].length - 1) - neighbors.add(new Integer[] {i + 1, j + 1}); + if (i < board.length - 1) neighbors.add(new Integer[] {i + 1, j}); - if (i < board.length - 1 && j > 0) neighbors.add(new Integer[] {i + 1, j - 1}); + if (j > 0) neighbors.add(new Integer[] {i, j - 1}); - if (i > 0) neighbors.add(new Integer[] {i - 1, j}); + if (j < board[0].length - 1) neighbors.add(new Integer[] {i, j + 1}); - 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; - } + return neighbors; + } } // Trie used to optimize string search class TrieNode { - Map children = new HashMap<>(); - String word = ""; + Map children = new HashMap<>(); + String word = ""; } class Trie { - TrieNode root; - char endSymbol; + TrieNode root; + char endSymbol; - public Trie() { - this.root = new TrieNode(); - this.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; + 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; + } }