欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

剑指offer65:矩阵中的路径(二维数组,二分查找)

程序员文章站 2022-04-11 08:08:33
1 题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e ......

1 题目描述

  请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bccced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

2 思路和方法 

  回溯法:是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

  首先在矩阵中任意选取一个格子作为起点。假设矩阵中某个格子的字符为ch,并且这个格子对应于路径上的第i个字符。如果路径上的第i个字符不是ch,那么这个格子不可能处在路径的第i个位置上。如果路径的第i个字符恰好是ch,那么到相邻的格子上寻找第i+1个字符。重复这个过程直到路径上的所有字符都在矩阵中找到相应的位置。由于回溯法的递归特性,路径可以被看做一个栈。

  解题注意事项:

  (1)应该有一个布尔值矩阵来记录矩阵的哪些格子已经被使用过了
  (2)使用递归的方式求解。在使用递归的时候应该注意,在退出递归的时候需要根据需求对计数或者标志进行回退或者清除等操作。

3 c++核心代码

 1 class solution {
 2 public:
 3     bool haspathcore(const char *matrix, int rows, int cols, int row, int col, const char *str, int &pathlen, bool *visited)
 4     {
 5         //一定注意开头两个判定的顺序,如果str已经全部监测了,那么就直接返回true,不需要进行下一步检测
 6         if (str[pathlen] == '\0')return true;
 7 
 8         //需要进一步检测才检查状态对不对
 9         if ((row < 0) || (col < 0) || (row >= rows) || (col >= cols) || (visited[row*cols + col]))return false;
10 
11         bool resu = false;
12         //检查当前字符是否满足
13         if (matrix[row*cols + col] == str[pathlen]){
14             pathlen++;
15             visited[row*cols + col] = true;
16 
17             resu = haspathcore(matrix, rows, cols, row + 1, col, str, pathlen, visited) ||
18                    haspathcore(matrix, rows, cols, row - 1, col, str, pathlen, visited) ||
19                    haspathcore(matrix, rows, cols, row, col - 1, str, pathlen, visited) ||
20                    haspathcore(matrix, rows, cols, row, col + 1, str, pathlen, visited);
21 
22             //如果resu为假,当前格子不可能处在路径的第pathlen个位置上(所有可能性都检查了)
23             if (!resu){
24                 pathlen--;                          //从当前分支退出,把pathlength减回去,visited清空
25                 visited[row*cols + col] = false;
26             }
27         }
28         return resu;
29     }
30     
31     bool haspath(char* matrix, int rows, int cols, char* str)
32     {
33         if ((matrix == null) || (rows <= 0) || (cols <= 0) || (str == null)){
34             return false;
35         }
36 
37         bool *visited = (bool *)malloc(rows*cols);
38        //bool *visited = new bool[rows * cols]; //记录当前路径已访问的节点
39         memset(visited, false, rows*cols);
40 
41         bool resu;
42         int pathlen = 0;
43         //遍历所有可能的入口,发现第一条路径时就结束
44         for (int i = 0; i != rows; i++){
45             for (int j = 0; j != cols; j++){
46                 if (haspathcore(matrix, rows, cols, i, j, str, pathlen, visited)){
47                     free(visited);
48                     return true;
49                 }
50             }
51         }
52         free(visited);
53         return false;
54     }
55 };

参考资料

https://blog.csdn.net/m0_37950361/article/details/80546981