[LeetCode OJ] Word Search 深度优先搜索DFS
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"
, -> returns true
,
word = "SEE"
, -> returns true
,
word = "ABCB"
, -> returns false
.
典型的搜索问题,这道题目用了两种方法来做。
一种用到动态规划的思想,用一个vector记录下word中前i个字符构成的子串的所有搜索路径,然后对于前i+1个字符构成的子串
查找搜索路径时,只需判断第i+1个字符在当前由前i个字符构成的子串的搜索路径的最后一个位置的上下左右四个方向是否出现,
如果出现则保存新的路径。最后只需判断查找word时是否有可行的搜索路径存在,如果有,则返回true,否则,返回false。但是,
这种方法的复杂度很高,对于大的测试数据,出现TLE。
1 class Solution { 2 public: 3 bool exist(vector<vector<char> > &board, string word) { 4 map<int, vector<vector<unsigned> > > path; //path[i]表示word中的前i个字符构成的字符串在board中的查找路径,一共有path[i].size()条合法查找路径 5 if(word.size()==0) 6 return true; 7 int width = board[0].size(); 8 for(unsigned i=0; i<board.size()*width; i++) 9 { 10 if(board[i/width][i%width]==word[0]) 11 { 12 vector<unsigned> start; 13 start.push_back(i); 14 path[1].push_back(start); 15 } 16 } 17 for(unsigned i=1; i<word.size(); i++) 18 { 19 char c = word[i]; 20 //vector<vector<unsigned> > pt = path[i-1]; 21 22 for(vector<vector<unsigned> >::iterator it=path[i].begin(); it!=path[i].end(); it++) 23 { 24 vector<unsigned> unipath = *it; 25 26 int lastpos = unipath.back(); 27 28 if((lastpos-width)>=0 && board[(lastpos-width)/width][(lastpos-width)%width]==c && find(unipath.begin(), unipath.end(), (lastpos-width))==unipath.end()) 29 { 30 unipath.push_back(lastpos-width); 31 path[i+1].push_back(unipath); 32 unipath.pop_back(); 33 } 34 if((lastpos+width)<(board.size()*width) && board[(lastpos+width)/width][(lastpos+width)%width]==c && find(unipath.begin(), unipath.end(), (lastpos+width))==unipath.end()) 35 { 36 unipath.push_back(lastpos+width); 37 path[i+1].push_back(unipath); 38 unipath.pop_back(); 39 } 40 if(lastpos%width>0 && board[(lastpos-1)/width][(lastpos-1)%width]==c && find(unipath.begin(), unipath.end(), (lastpos-1))==unipath.end()) 41 { 42 unipath.push_back(lastpos-1); 43 path[i+1].push_back(unipath); 44 unipath.pop_back(); 45 } 46 if((lastpos%width)<(width-1) && board[(lastpos+1)/width][(lastpos+1)%width]==c && find(unipath.begin(), unipath.end(), (lastpos+1))==unipath.end()) 47 { 48 unipath.push_back(lastpos+1); 49 path[i+1].push_back(unipath); 50 unipath.pop_back(); 51 } 52 if(i==word.size()-1 && path[word.size()].size()!=0) 53 return true; 54 } 55 } 56 if(path[word.size()].size()==0) 57 return false; 58 else 59 return true; 60 } 61 };
第二种是用到DFS(深度优先搜索),先找到可行的起始点,然后对于每个起始点判断是否有一条合法搜索路径存在,如果找到
一条合法搜索路径,则不进行后续搜索,直接返回true。如果所有可能的路径验证都不成立后,最后返回false。测试AC。
1 void search(vector<vector<char> > &board, string word, vector<int> &path, bool &flag) 2 { 3 if(word.size()==0) 4 { 5 flag = true; 6 return; 7 } 8 9 int width = board[0].size(); 10 char c = word[0]; 11 if(path.size()==0) 12 { 13 for(unsigned i=0; i<board.size()*width; i++) 14 { 15 if(board[i/width][i%width]==c) 16 { 17 path.push_back(i); 18 search(board, word.substr(1), path, flag); 19 if(flag==true) 20 return; 21 path.pop_back(); 22 } 23 } 24 } 25 else 26 { 27 int lastpos = path.back(); 28 if((lastpos-width)>=0 && board[(lastpos-width)/width][(lastpos-width)%width]==c && find(path.begin(), path.end(), (lastpos-width))==path.end()) 29 { 30 path.push_back(lastpos-width); 31 search(board, word.substr(1), path, flag); 32 if(flag==true) 33 return; 34 path.pop_back(); 35 } 36 if((lastpos+width)<(board.size()*width) && board[(lastpos+width)/width][(lastpos+width)%width]==c && find(path.begin(), path.end(), (lastpos+width))==path.end()) 37 { 38 path.push_back(lastpos+width); 39 search(board, word.substr(1), path, flag); 40 if(flag==true) 41 return; 42 path.pop_back(); 43 } 44 if(lastpos%width>0 && board[(lastpos-1)/width][(lastpos-1)%width]==c && find(path.begin(), path.end(), (lastpos-1))==path.end()) 45 { 46 path.push_back(lastpos-1); 47 search(board, word.substr(1), path, flag); 48 if(flag==true) 49 return; 50 path.pop_back(); 51 } 52 if((lastpos%width)<(width-1) && board[(lastpos+1)/width][(lastpos+1)%width]==c && find(path.begin(), path.end(), (lastpos+1))==path.end()) 53 { 54 path.push_back(lastpos+1); 55 search(board, word.substr(1), path, flag); 56 if(flag==true) 57 return; 58 path.pop_back(); 59 } 60 61 } 62 63 } 64 65 class Solution { 66 public: 67 bool exist(vector<vector<char> > &board, string word) { 68 bool flag = false; 69 vector<int> path; 70 71 search(board, word, path, flag); 72 73 return flag; 74 } 75 };