[Leetcode] word search 单词查询
Given a 2D board and a word, find if the word exists in the grid.
The word can 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.
For example,
Given board =
[ ["ABCE"], ["SFCS"], ["ADEE"] ]
word ="ABCCED", -> returnstrue,
word ="SEE", -> returnstrue,
word ="ABCB", -> returnsfalse.
题意:从一个二维矩阵中找到给定单词,某个单词的下一个字符,只能从其上下左右中寻找。
思路:刚开始想到用广搜,但是,因为单词的首字符在二维数组中可能有不止一个与其对应,不合适,所以正确合适的开启方式是DFS。后来再一想,这题和surrounded regions类似,用DFS对当前位置的上下左右进行深搜,若和单词中的下一个字符相等,则从单词的下一个位置开始,重新搜索。因为题总要求,在某一次的搜索过程中,字符只能使用一次,所以对搜索过的字符要设置标识符标识已经访问过了。设置标识符有两种方法一种是:将访问过的字符设置为其他的字符,如'#',等这次搜索返回时要将其恢复到原来的字符;二是,开辟一个和元素组等大小的二维数组,标识某个字符是否被访问过,不过还是得恢复。
参考JustDoIT,代码一:
1 class Solution { 2 public: 3 bool exist(vector<vector<char> > &board, string word) 4 { 5 if(word.size()==0) return true; 6 int row=board.size(),col=board[0].size(); 7 if(row==0||col==0) return false; 8 9 for(int i=0;i<row;++i) 10 { 11 for(int j=0;j<col;++j) 12 { 13 if(board[i][j]==word[0]&&dfs(i,j,word,0,board)) 14 return true; 15 } 16 } 17 return false; 18 } 19 bool dfs(int row,int col,string &word,int index,vector<vector<char>> &board) 20 { 21 if(index==word.size()-1) return true; 22 char temp=board[row][col]; 23 24 board[row][col]='#'; 25 if(row>0&&board[row-1][col]==word[index+1]) 26 if(dfs(row-1,col,word,index+1,board)) 27 return true; 28 29 if(row<board.size()-1&&board[row+1][col]==word[index+1]) 30 if(dfs(row+1,col,word,index+1,board)) 31 return true; 32 33 if(col>0&&board[row][col-1]==word[index+1]) 34 if(dfs(row,col-1,word,index+1,board)) 35 return true; 36 37 if(col<board[0].size()-1&&board[row][col+1]==word[index+1]) 38 if(dfs(row,col+1,word,index+1,board)) 39 return true; 40 41 board[row][col]=temp; 42 return false; 43 44 } 45 };
参考Grandyang代码二:通过使用二维标识数组来实现,但要避免使用vector<bool>,原因见这里。代码见下:
1 class Solution { 2 public: 3 bool exist(vector<vector<char> > &board, string word) 4 { 5 if(word.empty()) return true; 6 if(board.empty()||board[0].empty()) return false; 7 8 //bool型的数组 9 vector<vector<bool>> visited(board.size(),vector<bool>(board[0].size(),false)); 10 for(int i=0;i<board.size();++i) 11 for(int j=0;j<board[i].size();++j) 12 { 13 if(search(board,word,0,i,j,visited)) 14 return true; 15 } 16 return false; 17 } 18 19 bool search(vector<vector<char>> &board,string word,int idx,int i,int j, 20 vector<vector<bool>> &visited) 21 { 22 if(idx==word.size()) return true; 23 if(i<0||j<0||i>=board.size()||j>=board[0].size()||visited[i][j]|| 24 board[i][j] !=word[idx]) 25 return false; 26 27 visited[i][j]=true; 28 bool res=search(board,word,idx+1,i-1,j,visited) 29 ||search(board,word,idx+1,i+1,j,visited) 30 ||search(board,word,idx+1,i,j-1,visited) 31 ||search(board,word,idx+1,i,j+1,visited); 32 33 //重置,是因为一下一个元素为起点的遍历可以重新访问上节点访问过的 34 visited[i][j]=false; 35 return res; 36 } 37 };
针对第一方法用第二方法的形式简化,代码如下:
1 class Solution { 2 public: 3 bool exist(vector<vector<char> > &board, string word) 4 { 5 6 if(word.size()==0) return true; 7 int row=board.size(),col=board[0].size(); 8 if(row==0||col==0) return false; 9 10 for(int i=0;i<row;++i) 11 { 12 for(int j=0;j<col;++j) 13 { 14 if(board[i][j]==word[0]&&dfs(i,j,word,0,board)) 15 return true; 16 } 17 } 18 return false; 19 } 20 bool dfs(int row,int col,string &word,int index,vector<vector<char>> &board) 21 { 22 if(index==word.size()) return true; 23 char temp=board[row][col]; 24 25 if(row<0||row>=board.size()||col<0||col>=board[0].size()||board[row][col] =='#' 26 ||board[row][col] !=word[index]) 27 return false; 28 29 board[row][col]='#'; 30 bool res=dfs(row-1,col,word,index+1,board) 31 ||dfs(row+1,col,word,index+1,board) 32 ||dfs(row,col-1,word,index+1,board) 33 ||dfs(row,col+1,word,index+1,board); 34 35 board[row][col]=temp; 36 return res; 37 } 38 };
注意方法一和方法二的下标范围。