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


Myosotis
89 声望13 粉丝