回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
解题的一般步骤是:
1.定义一个解空间,它包含问题的解;(本题为flag)
2.利用适于搜索的方法组织解空间;(本题采用遍历)
3.利用限界函数避免移动到不可能产生解的子空间。(匹配判断,即剪枝策略)
4.利用深度优先法(DFS)搜索解空间;(上下左右搜索)
2018.3.9
例题:求矩阵中是否包含某条路径
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
int flag[] = new int[matrix.length];//解空间
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {//遍历每个点作为起始点
if (helper(matrix, rows, cols, i, j, str, 0, flag))//从某点开始匹配第1个字符
return true;
}
}
return false;
}
private boolean helper(char[] matrix, int rows, int cols, int i, int j, char[] str, int k, int[] flag) {
int index = i * cols + j;//走到的位置
if (i < 0 || i >= rows || j < 0 || j >= cols || matrix[index] != str[k] || flag[index] == 1)//验证判断1.越过边界则退回 2.目前的点不是要找的点退回 3.目前的点已经在匹配队列中
return false;//匹配失败
//走到这一步说明该点已经匹配成功了
if(k == str.length - 1) return true;//如果目前匹配的字符已经是待匹配的
//最后一个字符了,那么直接返回(*)
flag[index] = 1;//将目前匹配的的这个点标记上
//往上下左右试探下一个(k+1)字符是否匹配,只要还有路径能继续走,就一直探索。
//一直试探到存在某个点全部匹配(到达(*))则一路退出递归返回true,
//否则(到达死胡同,上下左右都不通时)停止探索,清空匹配标志
//(将该点从匹配队列中去除)返回false回退
if (helper(matrix, rows, cols, i - 1, j, str, k + 1, flag)
|| helper(matrix, rows, cols, i + 1, j, str, k + 1, flag)
|| helper(matrix, rows, cols, i, j - 1, str, k + 1, flag)
|| helper(matrix, rows, cols, i, j + 1, str, k + 1, flag)) {
return true;
}
flag[index] = 0;//清空标志
return false;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。