diff --git a/README.md b/README.md index 15940100..cc6371b5 100644 --- a/README.md +++ b/README.md @@ -991,7 +991,7 @@ 131| [Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning/) |[Python](./leetcode_python/Backtracking/palindrome-partitioning.py), [Java](./leetcode_java/src/main/java/LeetCodeJava/BackTrack/PalindromePartitioning.java) | _O(n^2)_ ~ _O(2^n)_ | _O(n^2)_ | Medium |dfs, backtracking, good trick,`amazon`| AGAIN*********** (6) (MUST) 139| [Word Break](https://leetcode.com/problems/word-break/) | [Python](./leetcode_python/Backtracking/word-break.py), [Java](./leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordBreak.java) | _O(n * l^2)_ | _O(n)_ | Medium |Curated Top 75, backtracking, dfs, `dp`,`trick`,`UBER`,`yahoo`,`amazon`, `google`,`fb`| AGAIN**************** (7) (MUST) 140| [Word Break II](https://leetcode.com/problems/word-break-ii/) | [Python](./leetcode_python/Backtracking/word-break-ii.py) | _O(n * l^2)_ | _O(n)_ | Hard |good basic, LC 078, backtracking, dfs, `dp`,`trick`, `amazon`| AGAIN******** (2) -212| [Word Search II](https://leetcode.com/problems/word-search-ii/) | [Python](./leetcode_python/Backtracking/word-search-ii.py) | _O(m * n * l)_ | _O(l)_ | Hard |Curated Top 75, LC 208, LC 079, hashset, hashmap, trie, backtrack with trie, `amazon`, fb, apple, twitter, uber, google, indeed| AGAIN********** (3) +212| [Word Search II](https://leetcode.com/problems/word-search-ii/) | [Python](./leetcode_python/Backtracking/word-search-ii.py), [Java](./leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordSearch2.java) | _O(m * n * l)_ | _O(l)_ | Hard |Curated Top 75, LC 208, LC 079, hashset, hashmap, trie, backtrack with trie, `amazon`, fb, apple, twitter, uber, google, indeed| AGAIN********** (3) 216| [Combination Sum III](https://leetcode.com/problems/combination-sum-iii/)| [Python](./leetcode_python/Backtracking/combination-sum-iii.py) | _O(k * C(n, k))_ | _O(k)_ | Medium || AGAIN* 254| [Factor Combinations](https://leetcode.com/problems/factor-combinations/) | [Python](./leetcode_python/Backtracking/factor-combinations.py) | _O(nlogn)_ | _O(logn)_ | Medium |🔒| AGAIN (not start) 267| [Palindrome Permutation II](https://leetcode.com/problems/palindrome-permutation-ii/) | [Python](./leetcode_python/Backtracking/palindrome-permutation-ii.py) | _O(n * n!)_ | _O(n)_ | Medium |🔒| AGAIN (not start*) diff --git a/data/progress.txt b/data/progress.txt index d0bfe313..6cd05ee2 100644 --- a/data/progress.txt +++ b/data/progress.txt @@ -1,4 +1,4 @@ -20240309: 207(again!!!),208,211(again) +20240309: 207(again!!!),208,211(again),212 20240308: 152,153(again),190,191,198,200,206(again) 20240307: 139(again),141,143(again) 20240306: 121,124(again),125,128,133(again) diff --git a/data/to_review.txt b/data/to_review.txt index 6233c07c..88bbb6a1 100644 --- a/data/to_review.txt +++ b/data/to_review.txt @@ -1,4 +1,4 @@ -2024-05-03 -> ['207(again!!!),208,211(again)'] +2024-05-03 -> ['207(again!!!),208,211(again),212'] 2024-05-02 -> ['152,153(again),190,191,198,200,206(again)'] 2024-05-01 -> ['139(again),141,143(again)'] 2024-04-30 -> ['121,124(again),125,128,133(again)'] @@ -8,7 +8,7 @@ 2024-04-24 -> ['39,48(again),49,53,54'] 2024-04-23 -> ['20,21,23,33(again)'] 2024-04-22 -> ['1,3,5,4,19'] -2024-04-12 -> ['207(again!!!),208,211(again)'] +2024-04-12 -> ['207(again!!!),208,211(again),212'] 2024-04-11 -> ['152,153(again),190,191,198,200,206(again)'] 2024-04-10 -> ['139(again),141,143(again)'] 2024-04-09 -> ['121,124(again),125,128,133(again)'] @@ -18,26 +18,26 @@ 2024-04-03 -> ['39,48(again),49,53,54'] 2024-04-02 -> ['20,21,23,33(again)'] 2024-04-01 -> ['1,3,5,4,19'] -2024-03-30 -> ['207(again!!!),208,211(again)'] +2024-03-30 -> ['207(again!!!),208,211(again),212'] 2024-03-29 -> ['152,153(again),190,191,198,200,206(again)'] 2024-03-28 -> ['139(again),141,143(again)'] 2024-03-27 -> ['121,124(again),125,128,133(again)'] 2024-03-26 -> ['100,102,104,105(again)'] 2024-03-25 -> ['73,76,79(again),91,25'] 2024-03-24 -> ['55(again),56,62,70'] -2024-03-22 -> ['207(again!!!),208,211(again)'] +2024-03-22 -> ['207(again!!!),208,211(again),212'] 2024-03-21 -> ['152,153(again),190,191,198,200,206(again)', '39,48(again),49,53,54'] 2024-03-20 -> ['139(again),141,143(again)', '20,21,23,33(again)'] 2024-03-19 -> ['121,124(again),125,128,133(again)', '1,3,5,4,19'] 2024-03-18 -> ['100,102,104,105(again)'] -2024-03-17 -> ['207(again!!!),208,211(again)', '73,76,79(again),91,25'] +2024-03-17 -> ['207(again!!!),208,211(again),212', '73,76,79(again),91,25'] 2024-03-16 -> ['152,153(again),190,191,198,200,206(again)', '55(again),56,62,70'] 2024-03-15 -> ['139(again),141,143(again)'] -2024-03-14 -> ['207(again!!!),208,211(again)', '121,124(again),125,128,133(again)'] +2024-03-14 -> ['207(again!!!),208,211(again),212', '121,124(again),125,128,133(again)'] 2024-03-13 -> ['152,153(again),190,191,198,200,206(again)', '100,102,104,105(again)', '39,48(again),49,53,54'] -2024-03-12 -> ['207(again!!!),208,211(again)', '139(again),141,143(again)', '73,76,79(again),91,25', '20,21,23,33(again)'] -2024-03-11 -> ['207(again!!!),208,211(again)', '152,153(again),190,191,198,200,206(again)', '121,124(again),125,128,133(again)', '55(again),56,62,70', '1,3,5,4,19'] -2024-03-10 -> ['207(again!!!),208,211(again)', '152,153(again),190,191,198,200,206(again)', '139(again),141,143(again)', '100,102,104,105(again)'] +2024-03-12 -> ['207(again!!!),208,211(again),212', '139(again),141,143(again)', '73,76,79(again),91,25', '20,21,23,33(again)'] +2024-03-11 -> ['207(again!!!),208,211(again),212', '152,153(again),190,191,198,200,206(again)', '121,124(again),125,128,133(again)', '55(again),56,62,70', '1,3,5,4,19'] +2024-03-10 -> ['207(again!!!),208,211(again),212', '152,153(again),190,191,198,200,206(again)', '139(again),141,143(again)', '100,102,104,105(again)'] 2024-03-09 -> ['152,153(again),190,191,198,200,206(again)', '139(again),141,143(again)', '121,124(again),125,128,133(again)', '73,76,79(again),91,25'] 2024-03-08 -> ['139(again),141,143(again)', '121,124(again),125,128,133(again)', '100,102,104,105(again)', '55(again),56,62,70', '39,48(again),49,53,54'] 2024-03-07 -> ['121,124(again),125,128,133(again)', '100,102,104,105(again)', '73,76,79(again),91,25', '20,21,23,33(again)'] diff --git a/leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordSearch2.java b/leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordSearch2.java index dead1bc9..a74c38d9 100644 --- a/leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordSearch2.java +++ b/leetcode_java/src/main/java/LeetCodeJava/BackTrack/WordSearch2.java @@ -2,13 +2,198 @@ // https://leetcode.com/problems/word-search-ii/description/?envType=list&envId=xoqag3yj +import java.util.ArrayList; import java.util.List; public class WordSearch2 { // V0 - public List findWords(char[][] board, String[] words) { - return null; + // TODO : implement +// public List findWords(char[][] board, String[] words) { +// return null; +// } + + // V1 + // IDEA : BACKTRACK + TRIE + // https://leetcode.com/problems/word-search-ii/solutions/59780/java-15ms-easiest-solution-100-00/ + public List findWords2(char[][] board, String[] words) { + List res = new ArrayList<>(); + TrieNode root = buildTrie(words); + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + dfs (board, i, j, root, res); + } + } + return res; + } + + public void dfs(char[][] board, int i, int j, TrieNode p, List res) { + char c = board[i][j]; + if (c == '#' || p.next[c - 'a'] == null) return; + p = p.next[c - 'a']; + if (p.word != null) { // found one + res.add(p.word); + p.word = null; // de-duplicate + } + + board[i][j] = '#'; + if (i > 0) dfs(board, i - 1, j ,p, res); + if (j > 0) dfs(board, i, j - 1, p, res); + if (i < board.length - 1) dfs(board, i + 1, j, p, res); + if (j < board[0].length - 1) dfs(board, i, j + 1, p, res); + board[i][j] = c; + } + + public TrieNode buildTrie(String[] words) { + TrieNode root = new TrieNode(); + for (String w : words) { + TrieNode p = root; + for (char c : w.toCharArray()) { + int i = c - 'a'; + if (p.next[i] == null) p.next[i] = new TrieNode(); + p = p.next[i]; + } + p.word = w; + } + return root; + } + + class TrieNode { + TrieNode[] next = new TrieNode[26]; + String word; + } + + // V2 + // IDEA : TRIE + BACKTRACK + // https://leetcode.com/problems/word-search-ii/solutions/4707890/backtracking-solution-using-trie-explained/ + class TrieNode2 { + private TrieNode2[] links; + private final int LENGTH = 26; + private boolean isWord = false; + + public TrieNode2() { + links = new TrieNode2[LENGTH]; + } + + // Check if the node contains a link to the given key + public boolean containsKey(char key) { + return links[key - 'a'] != null; + } + + // Retrieve the next node for the given key + public TrieNode2 get(char key) { + return links[key - 'a']; + } + + // Create a link for the given key to the node + public void put(char key, TrieNode2 node) { + links[key - 'a'] = node; + } + + // Mark this node as representing the end of a word + public void setWord(boolean isWord) { + this.isWord = isWord; + } + + // Check if this node represents the end of a word + public boolean isWord() { + return isWord; + } + } + + class Trie2 { + private TrieNode2 root; + + public Trie2() { + root = new TrieNode2(); + } + + // Insert a word into the trie + public void insert(String word) { + TrieNode2 node = root; + + for (char c : word.toCharArray()) { + + if (!node.containsKey(c)) { + node.put(c, new TrieNode2()); + } + node = node.get(c); + } + node.setWord(true); + } + + public TrieNode2 getRoot() { + return root; + } + } + + private final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; + + // Check if the given position is within the board boundaries + private boolean isValidCell(int row, int col, int rows, int cols) { + return row >= 0 && row < rows && col >= 0 && col < cols; + } + + // Build a trie from a list of words + private Trie2 buildTrie2(String[] words) { + Trie2 trie = new Trie2(); + + for (String word : words) { + trie.insert(word); + } + return trie; + } + + // Backtrack to find all words starting from (row, col) + private void backTrack(char[][] board, boolean[][] visited, int row, int col, TrieNode2 node, StringBuilder word, List result) { + if (node.isWord()) { + result.add(word.toString()); + node.setWord(false); // Avoid duplicate entries + } + + if (!isValidCell(row, col, board.length, board[0].length) || visited[row][col]) { + return; + } + visited[row][col] = true; + + for (int[] dir : DIRECTIONS) { + int newRow = row + dir[0]; + int newCol = col + dir[1]; + + if (isValidCell(newRow, newCol, board.length, board[0].length) && !visited[newRow][newCol]) { + char nextChar = board[newRow][newCol]; + + if (node.containsKey(nextChar)) { + word.append(nextChar); + backTrack(board, visited, newRow, newCol, node.get(nextChar), word, result); + word.deleteCharAt(word.length() - 1); // Backtrack + } + } + } + + visited[row][col] = false; // Reset visited status for backtracking + } + + public List findWords2_(char[][] board, String[] words) { + List result = new ArrayList<>(); + + Trie2 trie = buildTrie2(words); + TrieNode2 root = trie.getRoot(); + + boolean[][] visited = new boolean[board.length][board[0].length]; + + for (int row = 0; row < board.length; row++) { + + for (int col = 0; col < board[0].length; col++) { + + if (root.containsKey(board[row][col])) { + StringBuilder word = new StringBuilder(); + word.append(board[row][col]); + backTrack(board, visited, row, col, root.get(board[row][col]), word, result); + } + } + } + return result; } }