【leetcode】212. Word Search II
Given an m x n board of characters and a list of strings words, return all words on the board. Each word must be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
这个题目相比于word search来说不是对一个word进行检索,而是对多个word 进行检索,可以对在79题目的基础上进行修改 ,增加一个循环,得到一个基本的解法,但是时间复杂度较高,没法oc
class Solution { public: bool dfs(vector<vector<char>>& board,string word,int i,int j,int n){ //递归终止条件 if(n==word.size()) return true; if(i<0 || j<0 || i>=board.size()||j>=board[0].size() || board[i][j]!=word[n]) return false; board[i][j]='0';//这个位置检索到了 bool flag=(dfs(board,word,i+1,j,n+1) || dfs(board,word,i-1,j,n+1)|| dfs(board,word,i,j+1,n+1)|| dfs(board,word,i,j-1,n+1)); board[i][j]=word[n]; return flag; } vector<string> findWords(vector<vector<char>>& board, vector<string>& words) { //word search plus版本 word search 是检索一个word 这个版本是每个word都进行检索 // 一个单词一个单词的去检索 int m=board.size(),n=board[0].size(); vector<string>res; for(auto word:words){ for(int i=0;i<m;++i){ for(int j=0;j<n;++j){ if(dfs(board,word,i,j,0)){ res.push_back(word); i=m; j=n;//跳出循环 } } } } return res; } };
如何优化这个题目呢,能不能并发的对多个word同时进行检索呢? 通过字典树来实现快速查询。
class Solution { int dir[5]={1,0,-1,0,1};//检索方向 public: //嵌套类 构建一个前缀树 class Trie{ public: string s; Trie *next[26]; public: Trie() { s=""; memset(next,0,sizeof(next));//初始化多叉树的索引 } void insert(string word){ Trie *node=this; for(auto ww:word){ if(node->next[ww-'a']==NULL){ node->next[ww-'a']=new Trie(); } node=node->next[ww-'a']; } node->s=word; } }; vector<string> findWords(vector<vector<char>>& board, vector<string>& words) { vector<string> res; if(board.size()==0 || board[0].size()==0 || words.size()==0) return res; vector<vector<bool>> dp(board.size(),vector<bool>(board[0].size(),false)); Trie *T=new Trie(); for(auto word:words){ T->insert(word); } for(int i=0;i<board.size();++i){ for(int j=0;j<board[0].size();++j){ if(T->next[board[i][j]-'a']!=NULL){ search(board,T->next[board[i][j]-'a'],i,j,dp,res); } } } return res; } void search(vector<vector<char>>& board, Trie* p, int i, int j, vector<vector<bool>>& dp, vector<string>& res) { if (!p->s.empty()) { res.push_back(p->s); p->s.clear(); } dp[i][j] = true; for (int ii=0;ii<4;++ii) { int nx = i + dir[ii], ny = j + dir[ii+1]; if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size() && !dp[nx][ny] && p->next[board[nx][ny] - 'a']) { search(board, p->next[board[nx][ny] - 'a'], nx, ny, dp, res); } } dp[i][j] = false; } };
同样也可以用结构体来构建一个前缀树:
class Solution { public: struct TrieNode { TrieNode *child[26]; string str; }; struct Trie { TrieNode *root; Trie() : root(new TrieNode()) {} void insert(string s) { TrieNode *p = root; for (auto &a : s) { int i = a - 'a'; if (!p->child[i]) p->child[i] = new TrieNode(); p = p->child[i]; } p->str = s; } }; vector<string> findWords(vector<vector<char>>& board, vector<string>& words) { vector<string> res; if (words.empty() || board.empty() || board[0].empty()) return res; vector<vector<bool>> visit(board.size(), vector<bool>(board[0].size(), false)); Trie T; for (auto &a : words) T.insert(a); for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { if (T.root->child[board[i][j] - 'a']) { search(board, T.root->child[board[i][j] - 'a'], i, j, visit, res); } } } return res; } void search(vector<vector<char>>& board, TrieNode* p, int i, int j, vector<vector<bool>>& visit, vector<string>& res) { if (!p->str.empty()) { res.push_back(p->str); p->str.clear(); } int d[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; visit[i][j] = true; for (auto &a : d) { int nx = a[0] + i, ny = a[1] + j; if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size() && !visit[nx][ny] && p->child[board[nx][ny] - 'a']) { search(board, p->child[board[nx][ny] - 'a'], nx, ny, visit, res); } } visit[i][j] = false; } };