请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的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
提示:
- 1 <= board.length <= 200
- 1 <= board[i].length <= 200
思路
思路类似笔记1,寻找岛屿。用一个二维数组作为标记数组,当检索过后进行标记。
主函数从头到尾扫描board,当首字母契合后,进入DFS进行检索。
检索时记得每经过一个字母,就进行标记。如果发现该字母不能继续下去,记得取消标记。
答案
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <stack>
#include <set>
#include <queue>
#include <algorithm> //标准算法的头文件
using namespace std;
class Solution {
public:
int cnt=0; //统计查到多少word内的字母
bool exist(vector<vector<char>>& board, string word) {
vector<vector<int>>mark; //用来标记搜索过的元素 与board长得一样
vector<int> v(board[0].size(), 0);//0表示未搜索
for (int i = 0; i < board.size(); i++)
mark.push_back(v);
//从头到尾扫描所有元素
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board[i].size(); j++) {
//如果找到首字母且未标记
if (board[i][j] == word[0]) {
mark[i][j] = 1; //寻找到就标记
cnt = cnt + 1;
DFS(board, mark,word, i, j, 1);//DFS寻找
if (cnt == word.size())
return true;
cnt = 0;
mark.clear(); //当前DFS失败,记得清空
for (int i = 0; i < board.size(); i++)
mark.push_back(v);
}
}
}
return false; //扫描完成后 返回false
}
//index表示寻找到word当中的第几个字母
void DFS(vector<vector<char>>& board, vector<vector<int>>& mark,string word,int x,int y,int index) {
//cout << cnt << endl;
if (index == word.size())
return;
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 }; //方向数组 表示向四周寻找
for (int i = 0; i < 4; i++) {
int newx = dx[i] + x;
int newy = dy[i] + y;
if (newx<0 || newy<0 || newx>=board.size() || newy>=board[0].size())
continue; //取出超越边界的点
if (board[newx][newy] == word[index] && mark[newx][newy]==0) {
cnt = cnt + 1;
mark[newx][newy] = 1;
DFS(board, mark,word, newx, newy, index + 1);
if (cnt == word.size())
return;
cnt = cnt - 1; //失败注意回溯信息
mark[newx][newy] = 0;
}
}
}
};
void test02() {
/*vector<vector<char>> board = { {'A','B','C','E' },
{'S', 'F', 'C', 'S'},{'A', 'D', 'E', 'E'} };*/
/*vector<vector<char>> board = { {'C','A','A' },
{'A', 'A', 'A',},{'B', 'C', 'D'} };*/
/*vector<vector<char>> board = { {'A','B','C','E' },
{'S', 'F', 'E', 'S'},{'A', 'D', 'E', 'E'} };
string word = "ABCESEEEFS";*/
vector<vector<char>> board = { { 'A', 'A', 'A', 'A', 'A', 'A'},{'A', 'A', 'A', 'A', 'A', 'A'},{'A', 'A', 'A', 'A', 'A', 'A'},{'A', 'A', 'A', 'A', 'A', 'A'},{'A', 'A', 'A', 'A', 'A', 'A'},{'A', 'A', 'A', 'A', 'A', 'A'} };
string word = "AAAAAAAAAAAAAAB";
Solution solution;
cout<<solution.exist(board, word) << endl;
}
int main() {
test02();
system("pause");
return 0;
}
class Solution {
private:
string item;
void findRet(vector<vector<char>>&board,vector<vector<bool>>&mark,int i,int j,string word,int index) {
if(index==word.size())
return;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
for(int k=0;k<4;k++) {
int newx=i+dx[k];
int newy=j+dy[k];
if(newx<0||newy<0||newx>=board.size()||newy>=board[0].size())
continue; //去掉边界点
if(board[newx][newy]==word[index] && mark[newx][newy]==false) {
mark[newx][newy]=true;
item+=word[index];
findRet(board,mark,newx,newy,word,index+1);
if(item.compare(word)==0)
return;
item.pop_back(); //失败注意回溯
mark[newx][newy]=false;
}
}
}
public:
bool exist(vector<vector<char>>& board, string word) {
vector<vector<bool>> mark;
for(int i=0;i<board.size();i++)
mark.push_back(vector<bool>(board[i].size(),false));
for(int i=0;i<board.size();i++) {
for(int j=0;j<board[i].size();j++) {
if(board[i][j]==word[0]) {
mark[i][j]=true; //标记
item+=word[0];
findRet(board,mark,i,j,word,1);
if(item.compare(word)==0)
return true;
item.clear();
mark.clear(); //重建mark
for(int i=0;i<board.size();i++)
mark.push_back(vector<bool>(board[i].size(),false));
}
}
}
return false;
}
};