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