【C/C++练习题】回溯法判断矩阵中的路径

举报
王建峰 发表于 2021/11/19 02:52:06 2021/11/19
【摘要】 《剑指Offer》面试题12:矩阵中的路径 题目 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母...

《剑指Offer》面试题12:矩阵中的路径


题目

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
 


  
  1. A B T G
  2. C F C S
  3. J D E H

 

算法分析

对于这种一个问题有多个步骤,一个步骤又对应多个选项的问题,使用回溯法进行分析。基本思想是,首先对可选项(所有可能满足条件的选项)进行遍历,如果可选项满足规定的条件,将可选项作为下一个步骤;如果可选项中没有符合条件的结果,则返回上一个步骤,对其他可选项进行分析。直到最后一个步骤确定了,取得最终的结果。

另外,还要有一个数组,用来标记哪个步骤已经被执行过了,避免重复执行这个步骤。

 

问题分析

对于上述问题分析,"BFCE"是目标路径

  1. 所有选项都是可选项,通过遍历分析只有'B'符合条件
  2. 在‘B’的周围,'A' 'F' 'T'都是可选项,通过判断只有'B'下面的'F'符合条件
  3. 在'F'的周围,'B' 'C' 'D' 'C'都是可选项,通过判断有'F'左边的'C'和右边的'C'符合条件
  4. 在左'C'周围,'A' 'G'是可选项,但都不符合条件,退回上一个步骤'F'(分析其他可选项);
  5. 在右'C'周围,'T' 'F' 'E' 'S'都是可选项,'E'符合条件

上述是回溯法的分析过程

 

代码实现

由于回溯法的递归特性,这里使用递归的方法实现回溯分析


  
  1. #include "iostream"
  2. #include <cstring>
  3. #include <stack>
  4. using namespace std;
  5. bool hasPath(const char* matrix, int rows, int cols, const char* str);
  6. bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited);
  7. //回溯法进行矩阵中的路径判断
  8. //输入:源数组 matrix, 行数 rows, 列数 cols,目标字符串 str
  9. //输出:有目标路径 true, 无解 false
  10. bool hasPath(const char* matrix, int rows, int cols, const char* str)
  11. {
  12. //1.判断参数有效性
  13. if(matrix == nullptr || rows < 1 || cols < 1 || str == nullptr)
  14. return false;
  15. //2.设置标记路径的数组
  16. bool *visited = new bool[rows * cols];
  17. memset(visited, 0, rows * cols);
  18. int pathLength = 0;
  19. for(int row = 0; row < rows; ++row)
  20. {//3.遍历所有可选项,从可选项中选出符合条件的位置,进行回溯
  21. for(int col = 0; col < cols; ++col)
  22. {
  23. if(hasPathCore(matrix, rows, cols, row, col, str,
  24. pathLength, visited))
  25. {
  26. return true;
  27. }
  28. }
  29. }
  30. //4.清理堆空间
  31. delete[] visited;
  32. return false;
  33. }
  34. //递归方法实现回溯
  35. //输入:源数组 matrix, 行数 rows, 列数 cols,目标字符串 str,遍历深度 pathLength,标记数组 visited
  36. //输出:有目标路径 true, 无解 false
  37. bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited)
  38. {
  39. //1.递归结束条件,找到目标路径,回溯结束
  40. if(str[pathLength] == '\0')
  41. return true;
  42. bool hasPath = false;
  43. if(row >= 0 && row < rows && col >= 0 && col < cols
  44. && matrix[row * cols + col] == str[pathLength]
  45. && !visited[row * cols + col])
  46. {//1.递归判断条件,继续递归or返回结果
  47. ++pathLength;
  48. visited[row * cols + col] = true;
  49. //2.递归公式,从可选项中找出符合条件的选项,进行下一次递归
  50. hasPath = hasPathCore(matrix, rows, cols, row, col - 1,
  51. str, pathLength, visited)
  52. || hasPathCore(matrix, rows, cols, row - 1, col,
  53. str, pathLength, visited)
  54. || hasPathCore(matrix, rows, cols, row, col + 1,
  55. str, pathLength, visited)
  56. || hasPathCore(matrix, rows, cols, row + 1, col,
  57. str, pathLength, visited);
  58. if(!hasPath)
  59. {//3.可选项中没有符合条件的结果,退回上一个步骤
  60. --pathLength;
  61. visited[row * cols + col] = false;
  62. }
  63. }
  64. return hasPath;
  65. }
  66. //进行测试
  67. void test01()
  68. {
  69. const char* matrix = "ABTGCFCSJDEH";
  70. const char* str = "BFCE";
  71. if(hasPath(matrix, 3, 4, str) == true)
  72. printf("Passed.\n");
  73. else
  74. printf("FAILED.\n");
  75. }
  76. int main(int argc, char const *argv[])
  77. {
  78. test01();
  79. return 0;
  80. }

 

运行结果

 

文章来源: blog.csdn.net,作者:hinzer,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/feit2417/article/details/98305484

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。