回溯法經典問題——矩陣路徑

回溯算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。
解題的通常步驟是:
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;
    }
}
相關文章
相關標籤/搜索