212. Word Search II:多个单词查找
寫在前面:這兩周持續(xù)看花花醬整理的題目列表和視頻講解,也得益于自己持續(xù)多年刷題,今天刷這道題目的想法是:會(huì)trie樹居然就能攻克hard題目!我也離獨(dú)立攻破hard題目不遠(yuǎn)了嘛。前段時(shí)間看王爭在極客時(shí)間的系列課程,trie樹是不在話下的。好,開始寫題。
目錄
- 題目描述
- 暴力回溯
- Trie樹
題目描述
輸入:二維字符數(shù)組,做棋盤baord;字符串列表words。
返回:可以在棋盤中找到的所有單詞word。
規(guī)則:每個(gè)單詞需要按順序在棋盤中匹配,棋盤匹配的時(shí)候只能移動(dòng)相鄰位置。相鄰位置是指上下左右。
例子:輸入
board = [
[‘o’,‘a(chǎn)’,‘a(chǎn)’,‘n’],
[‘e’,‘t’,‘a(chǎn)’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]
words = [“oath”,“pea”,“eat”,“rain”]
輸出: [“eat”,“oath”]
暴力回溯
按照回溯法,每次解決一個(gè)單詞word。可以參考題目79。
參考例子中,board的行列:m=4,n=4。查找單詞word=oath。dfs搜索的時(shí)候每找到單詞中的一個(gè)字符作為一層。在每一層向下一層移動(dòng)過程中有上、下、左、右4種選擇。
枚舉每一個(gè)位置(i,j)作為起始查找位置。因?yàn)椴淮_定哪個(gè)位置的ch與word的第一個(gè)字符相同。
dfs(i,j,index),i:第i行;j:第j列;index:單詞中的第index個(gè)字符。
如果 board[i][j]=word[index],則設(shè)置board[i][j]=’#’,防止重復(fù)查找,繼續(xù)向4個(gè)方向遍歷。
當(dāng)index=word.length的時(shí)候,表示word是存在的,加入結(jié)果集。
當(dāng)數(shù)組下標(biāo)i,j越界,或者重復(fù)查找的時(shí)候返回。
如果board[i][j]!=word[index],則返回,不繼續(xù)搜索。
最終每個(gè)單詞查找一次,返回結(jié)果。
時(shí)間復(fù)雜度:$O(m?n?4l)O(m*n*4^l)O(m?n?4l),l=單詞長度
Trie樹
這里需要查找多個(gè)單詞。例如word=[“baa”,“bab”,“aaab”,“aaa”,“aaaa”]。單詞baa和bab有公共前綴ba,暴力回溯每次都從0開始查找,浪費(fèi)時(shí)間。如果能查找到baa之后回溯一步,繼續(xù)查找到bab就好了。單詞aaa和aaaa,也是同樣的情況。這里就需要用到Trie樹。Trie樹在有公共前綴子串的情況下,會(huì)極大的降低時(shí)間復(fù)雜度。Trie樹學(xué)習(xí)可以參考我的博客。
上圖展示了構(gòu)建完成的Trie樹結(jié)構(gòu)。這里在每個(gè)單詞結(jié)束位置添加了word表示當(dāng)前字符串的值。便于記錄結(jié)果。
和暴力回溯類似,遍歷每一個(gè)起始位置(i,j),從根節(jié)點(diǎn)開始查找。
dfs(i,j,node):每次查找到一個(gè)節(jié)點(diǎn),word不為空,說明找到了一個(gè)字符串,加入結(jié)果集并且word設(shè)置為null。
數(shù)組下標(biāo)i,j越界,或者重復(fù)訪問,則返回。
如果node.children[board[i][j]-‘a(chǎn)’]不為空,則繼續(xù)朝4個(gè)方向搜索。否則返回。
時(shí)間復(fù)雜度:構(gòu)建trie樹的時(shí)間復(fù)雜度是所有單詞長度和:$O(sum(l))。
搜索過程,因?yàn)橛泻喜⑺阉?#xff0c;所以最深的深度是max(l)。在每一層會(huì)查找4個(gè)方向,所以是O(4max(l))O(4^{max(l)})O(4max(l))
所以最終時(shí)間負(fù)責(zé)度是:O(sum(l)+4max(l))O(sum(l)+4^{max(l)})O(sum(l)+4max(l))
class Solution {private char[][] board;private String word;private int m;private int n;private TrieNode root;private List<String> result;public List<String> findWords(char[][] board, String[] words) {this.board = board;m = board.length;if(m == 0) return new ArrayList<String>();n = board[0].length;result = new ArrayList<String>();buildTree(words);for(int i=0;i<m;i++){for(int j=0;j<n;j++){dfs(i,j,root);}}return result;}private void dfs(int i,int j,TrieNode node){if(node.word!=null){result.add(node.word);node.word = null;}if(i<0 || i>=m || j<0 || j>=n || board[i][j]=='#'){return;} char ch = board[i][j];if(node.children[ch-'a']==null) return;TrieNode n = node.children[ch-'a'];board[i][j] = '#';dfs(i-1,j,n);dfs(i+1,j,n);dfs(i,j-1,n);dfs(i,j+1,n);board[i][j] = ch;}private void buildTree(String[] words){root = new TrieNode('/');for(String word : words){addWord(word);}}public void addWord(String word){TrieNode p = root;for(int i=0;i<word.length();i++){int idx = word.charAt(i)-'a';if(p.children[idx]==null){p.children[idx] = new TrieNode(word.charAt(i));}p = p.children[idx];}p.end = true;p.word = word;}class TrieNode{private char data;private boolean end;private TrieNode[] children = new TrieNode[26];private String word;public TrieNode(char data){this.data = data;}public boolean isEnd(){return end;}} }總結(jié)
以上是生活随笔為你收集整理的212. Word Search II:多个单词查找的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP自动测试框架Top 10
- 下一篇: 某公司数据恢复报告书