请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3×4的矩阵中包含一条字符串“bfce”的路径。
[[“a”,“b”,“c”,“e”],
[“s”,“f”,“c”,“s”],
[“a”,“d”,“e”,“e”]]
但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
示例 1:
输入:board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
输出:true
示例 2:
输入:board = [[“a”,“b”],[“c”,“d”]], word = “abcd”
输出:false
方法一:(未通过)
先想了一种用哈希集合记录走过的路径。先把字符串第一个数在数组中的位置找到,然后从这个位置开始上下左右移动,如果找不到就return false。
代码记录一下:
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
if(board.size()==0||board[0].size()==0)return false;
int gao=board.size();
int kuan=board[0].size();
int i,j;
int flag=0;
// vector<int>count;
for( i=0;i<gao;++i){
for( j=0;j<kuan;++j){
if(board[i][j]==word[0]){
flag=1;
break;//count.push_back(i*10+j);
}
if(flag==1)break;
}
}
if(flag==0)return false;
//while(!count.empty()){
// i=count[count.size()-1]/10;
// j=count[count.size()-1]%10;
// count.pop_back();
// int len=word.size();
unordered_set<int> visited;
visited.insert(i*10+j);
// len=len-1;
int k=1;
while(k<word.size()){
if(i-1>=0&&board[i-1][j]==word[k]&&(!visited.count(10*(i-1)+j))){
visited.insert((i-1)*10+j);
i=i-1;
// len--;
}
else if(i+1<gao&&board[i+1][j]==word[k]&&(!visited.count(10*(i+1)+j))){
visited.insert((i+1)*10+j);
i=i+1;
// len--;
}
else if(j-1>=0&&board[i][j-1]==word[k]&&(!visited.count(10*i+j-1))){
visited.insert(i*10+j-1);
j=j-1;
// len--;
}
else if(j+1<kuan&&board[i][j+1]==word[k]&&(!visited.count(10*i+j+1))){
visited.insert(i*10+j+1);
j=j+1;
// len--;
}
else return false;//else break;
k++;
//}
//if(len==0)return true;
}
return true;
}
};
在这个测试例子中没有通过,我写的这个应该是针对数组中没有重复数字是可行的(部分有重复数字的也可行)。
后来我又想,那是不是可以找个数组记录所有字符串第一个数字出现的位置。然后依次根据不同的位置进行查找。(代码里注释部分)。
然后我发现了一个问题,在这个不通过的例子里,查找第二个数时也有不同的路径,所以在循环里那四个if 的先后顺序就会捣乱。如果继续这样做,还要再加循环。太麻烦了,还是乖乖的回溯去吧。T_T
方法二:回溯法
回溯法+深度遍历。用递归
dfs的思路与这道题有相似之处 岛屿数量
class Solution {
public:
bool dfs(vector<vector<char>>& board, string word,int i,int j,int gao,int kuan,int num){
if(num==word.size())return true;
int x[4] = {0,0,-1,1};
int y[4] = {-1,1,0,0};
char tmp=board[i][j];
board[i][j]='.';//访问过这个点就把他沉降掉
for(int k=0;k<4;k++){
int dx=x[k]+i;
int dy=y[k]+j;
if(dx>=0&&dx<gao&&dy>=0&&dy<kuan&&word[num]==board[dx][dy])
if(dfs(board,word,dx,dy,gao,kuan,num+1))return true;
}
board[i][j]=tmp;
return false;
}
bool exist(vector<vector<char>>& board, string word) {
if(board.size()==0||board[0].size()==0)return false;
int gao=board.size();
int kuan=board[0].size();
for(int i=0;i<gao;++i){//与方法一相似,先找到字符串的第一个字符,然后进入递归。
for(int j=0;j<kuan;++j){
if(board[i][j]==word[0])
if(dfs(board,word,i,j,gao,kuan,1))return true;
}
}
return false;
}
};