矩阵中的路径:最直观的想法是,首先使用stxy变量存放矩阵matrix中出现的所有word起始位置元素的下标,然后以这些下标为起始开始dfs遍历,并使用tfxy变量存放矩阵matrix中的元素是否被访问,判断是否存在一条字符串路径,如果存在则直接返回true,如果所有均遍历完后仍不存在,则返回false。其中dfs遍历是这样的,首先判断字符串word是否已经访问结束,如果是则返回true,然后判断矩阵下标是否合法,如果不合法则返回false,接着判断矩阵元素是否等于字符串元素,如果是则记录元素已访问,并且返回上下左右四个方向的遍历。
bool dfs(vector<vector<char>>& matrix, vector<vector<bool>>& tfxy, int i, int j, string& word, int index) { if (index >= word.size()) //先要处理这个判断条件 否则[['A','A'],['A','A']] "AAAA" 就会出现错误 return true; if (i < 0 || i >= matrix.size() || j < 0 || j >= matrix[0].size() || tfxy[i][j] == true) //处理非法下标 return false; if (word[index] == matrix[i][j]) { tfxy[i][j] = true; return dfs(matrix, tfxy, i + 1, j, word, index + 1) || dfs(matrix, tfxy, i - 1, j, word, index + 1) || dfs(matrix, tfxy, i, j + 1, word, index + 1) || dfs(matrix, tfxy, i, j - 1, word, index + 1); } else return false; //不相等返回false return false; } bool hasPath(vector<vector<char> >& matrix, string word) { int n = matrix.size(), m = matrix[0].size(), len = word.size(); if (len > n * m) return false; char start = word[0]; vector<vector<int>> stxy; for (int i = 0; i < n; i++) //寻找起始节点 for (int j = 0; j < m; j++) if (matrix[i][j] == start) stxy.push_back({i, j}); for (auto stxys : stxy) { vector<vector<bool>> tfxy(n, vector<bool>(m, false)); //标记是否访问 bool flag = dfs(matrix, tfxy, stxys[0], stxys[1], word, 0); if (flag == true) return true; } return false; }
问题:但是这里存在几个问题:第一个是字符串word是否已经访问结束和矩阵下标是否合法的顺序不能反,否则[['A','A'],['A','A']] "AAAA"就会出现错误;第二个是[[A,B,C],[B,E,D],[F,G,G]],"ABCDEBF"或者[[A,B,F],[B,E,G],[C,D,G]],"ABCDEBF"两个案例无法通过,这就让我想起来,如果某一个元素其有多个方向是相同的下一个元素,但是按照我上述的方法dfs遍历后,如果先遍历的那一个方向是一个死胡同,那么程序是直接返回false的,但是事实上,我还可以回到原来的元素进行下一个方向的遍历,这明显是回溯法,于是最后通过的程序如下。
bool dfs(vector<vector<char>>& matrix, vector<vector<bool>>& tfxy, int i, int j,string& word, int index) { if (index >= word.size()) //先要处理这个判断条件 否则[['A','A'],['A','A']] "AAAA" 就会出现错误 return true; if (i < 0 || i >= matrix.size() || j < 0 || j >= matrix[0].size()|| matrix[i][j] !=word[index]||tfxy[i][j] == true) //处理非法下标 return false; tfxy[i][j] = true; bool res=dfs(matrix, tfxy, i, j + 1, word, index + 1) || dfs(matrix, tfxy, i + 1, j, word, index + 1) || dfs(matrix, tfxy, i - 1, j, word, index + 1)|| dfs(matrix, tfxy, i, j - 1, word, index + 1); tfxy[i][j]=false; //利用回溯法 否则[[A,B,C],[B,E,D],[F,G,G]],"ABCDEBF"会出错 //[[A,B,F],[B,E,G],[C,D,G]],"ABCDEBF" return res; } bool hasPath(vector<vector<char> >& matrix, string word) { int n = matrix.size(), m = matrix[0].size(), len = word.size(); if (len > n * m) return false; char start = word[0]; vector<vector<int>> stxy; for (int i = 0; i < n; i++) //寻找起始节点 for (int j = 0; j < m; j++) if (matrix[i][j] == start) stxy.push_back({i, j}); for (auto stxys : stxy) { vector<vector<bool>> tfxy(n, vector<bool>(m, false)); //标记是否访问 bool flag = dfs(matrix, tfxy, stxys[0], stxys[1], word, 0); if (flag == true) return true; } return false; }
总结:返回true的写在一起,返回false的写在一起,注意先后顺序。