回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
解题的通常步骤是:
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; } }