【LeetCode】Word Search II 解題報告,leetcodeii
【題目】
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
For example,
Given words = ["oath","pea","eat","rain"] and board =
[ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v']]
Return
["eat","oath"].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
【解析】
參考 【LeetCode】Word Search 解題報告,題目變成給定一組word,檢查哪個word可以由board形成。
如果還按照DFS回溯的方法,逐個檢查每個word是否在board裡,顯然效率是比較低的。我們可以利用Trie資料結構,也就是首碼樹。然後dfs時,如果當前形成的單詞不在Trie裡,就沒必要繼續dfs下去了。如果當前字串在trie裡,就說明board可以形成這個word。
【Java代碼】
public class Solution { Set<String> res = new HashSet<String>(); public List<String> findWords(char[][] board, String[] words) { Trie trie = new Trie(); for (String word : words) { trie.insert(word); } int m = board.length; int n = board[0].length; boolean[][] visited = new boolean[m][n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { dfs(board, visited, "", i, j, trie); } } return new ArrayList<String>(res); } public void dfs(char[][] board, boolean[][] visited, String str, int x, int y, Trie trie) { if (x < 0 || x >= board.length || y < 0 || y >= board[0].length) return; if (visited[x][y]) return; str += board[x][y]; if (!trie.startsWith(str)) return; if (trie.search(str)) { res.add(str); } visited[x][y] = true; dfs(board, visited, str, x - 1, y, trie); dfs(board, visited, str, x + 1, y, trie); dfs(board, visited, str, x, y - 1, trie); dfs(board, visited, str, x, y + 1, trie); visited[x][y] = false; }}
Trie資料結構的實現在LeetCode上也有對應的題目 Implement Trie (Prefix Tree)
【Trie實現】
class TrieNode { public TrieNode[] children = new TrieNode[26]; public String item = ""; // Initialize your data structure here. public TrieNode() { }}class Trie { private TrieNode root; public Trie() { root = new TrieNode(); } // Inserts a word into the trie. public void insert(String word) { TrieNode node = root; for (char c : word.toCharArray()) { if (node.children[c - 'a'] == null) { node.children[c - 'a'] = new TrieNode(); } node = node.children[c - 'a']; } node.item = word; } // Returns if the word is in the trie. public boolean search(String word) { TrieNode node = root; for (char c : word.toCharArray()) { if (node.children[c - 'a'] == null) return false; node = node.children[c - 'a']; } return node.item.equals(word); } // Returns if there is any word in the trie // that starts with the given prefix. public boolean startsWith(String prefix) { TrieNode node = root; for (char c : prefix.toCharArray()) { if (node.children[c - 'a'] == null) return false; node = node.children[c - 'a']; } return true; }}