给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.
题目实际上是很简单的题目,DFS+回溯足矣,但一开始的版本跑的时候总是在存在3个样例超时:
class Solution { public: bool exist(vector<vector<char>>& board, string word) { if(word.size()==0) return false; for(int row=0;row<board.size();row++) { for(int col=0;col<board[row].size();col++) { if(Core(board,word,0,row,col)) return true; } } return false; } bool Core(vector<vector<char>>& dict,string word,int pos,int row,int col) { if(pos==word.size()) return true; if(row<0||row>=dict.size()||col<0||col>=dict[row].size() ||dict[row][col]!=word[pos]) return false; dict[row][col]='#'; if(Core(dict,word,pos+1,row-1,col)||Core(dict,word,pos+1,row+1,col) ||Core(dict,word,pos+1,row,col-1)||Core(dict,word,pos+1,row,col+1)) return true; return false; } };
这个版本的回溯实际上是依靠值传递参数的特性来进行的,每次传递矩阵进去,修改的是副本的矩阵而不是原矩阵,因此也导致了超时,因为每次传递一次都要重新构造一个矩阵。
下面的版本将使用引用传递,回溯依靠自己在使用修改后使用临时保存的变量修改回来。
class Solution { public: bool exist(vector<vector<char>>& board, string word) { if(word.size()==0) return false; for(int row=0;row<board.size();row++) { for(int col=0;col<board[row].size();col++) { if(Core(board,word,0,row,col)) return true; } } return false; } bool Core(vector<vector<char>>& dict,string& word,int pos,int row,int col) { if(pos==word.size()) return true; if(row<0||row>=dict.size()||col<0||col>=dict[row].size() ||dict[row][col]!=word[pos]) return false; char tmp=dict[row][col]; dict[row][col]='#'; if(Core(dict,word,pos+1,row-1,col)||Core(dict,word,pos+1,row+1,col) ||Core(dict,word,pos+1,row,col-1)||Core(dict,word,pos+1,row,col+1)) return true; dict[row][col]=tmp; return false; } };
在dict和word都使用了引用传递后,时间复杂度上超越了99%,而原本在样例上都有超时的样例。
在这种复杂度比较高的题目里,使用引用传递真的非常重要