請設計乙個函式,用來判斷在乙個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意一格開始,每一步可以在矩陣中向左、右、上、下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格仔。例如,在下面的3×4的矩陣中包含一條字串「bfce」的路徑(路徑中的字母用加粗標出)。
[["a","b","c","e"],
["s","f","c","s"],
["a","d","e","e"]]
但矩陣中不包含字串「abfb」的路徑,因為字串的第乙個字元b佔據了矩陣中的第一行第二個格仔之後,路徑不能再次進入這個格仔。
示例 1:
輸入:board = [["a","b","c","e"],["s","f","c","s"],["a","d","e","e"]], word = "abcced"
輸出:true
示例 2:
1 <= board.length <= 200
1 <= board[i].length <= 200
演算法原理:
深度優先搜尋: 可以理解為暴力法遍歷矩陣中所有字串可能性。dfs 通過遞迴,先朝乙個方向搜到底,再回溯至上個節點,沿另乙個方向搜尋,以此類推。
剪枝: 在搜尋中,遇到 這條路不可能和目標字串匹配成功 的情況(例如:此矩陣元素和目標字元不同、此元素已被訪問),則應立即返回,稱之為 可行性剪枝 。
演算法剖析:
遞迴引數: 當前元素在矩陣 board 中的行列索引 i 和 j ,當前目標字元在 word 中的索引 k 。
終止條件:
返回 falsefalse : ① 行或列索引越界 或 ② 當前矩陣元素與目標字元不同 或 ③ 當前矩陣元素已訪問過 (③ 可合併至 ② ) 。
返回 truetrue : 字串 word 已全部匹配,即 k = len(word) - 1 。
遞推工作:
標記當前矩陣元素: 將 board[i][j] 值暫存於變數 tmp ,並修改為字元 '/' ,代表此元素已訪問過,防止之後搜尋時重複訪問。
搜尋下一單元格: 朝當前元素的 上、下、左、右 四個方向開啟下層遞迴,使用 或 連線 (代表只需一條可行路徑) ,並記錄結果至 res 。
還原當前矩陣元素: 將 tmp 暫存值還原至 board[i][j] 元素。
回溯返回值: 返回 res ,代表是否搜尋到目標字串。
**中,從每個節點 dfs 的順序為:下、上、右、左。
複雜度分析:
m,n 分別為矩陣行列大小, k為字串 word 長度。
時間複雜度 o(3^k *mn) : 最差情況下,需要遍歷矩陣中長度為 k字串的所有方案,時間複雜度為 o(3^k);矩陣中共有 mn 個起點,時間複雜度為 o(mn)。
方案數計算: 設字串長度為k,搜尋中每個字元有上、下、左、右四個方向可以選擇,捨棄回頭(上個字元)的方向,剩下 3種選擇,因此方案數的複雜度為 o(3^k) 。
空間複雜度 o(k): 搜尋過程中的遞迴深度不超過k,因此系統因函式呼叫累計使用的棧空間占用 o(k)(因為函式返回後,系統呼叫的棧空間會釋放)。最壞情況下 k =mn ,遞迴深度為 mn ,此時系統棧使用 o(mn)的額外空間。
劍指offer12 矩陣中的路徑
設計乙個函式,用來判斷在乙個矩陣中是否存在一條包含某個字串所有字元的路徑。路徑可以從矩陣中的任意一格開始,每一步可以在矩陣中向左 右 上 下移動一格。如果一條路徑經過了矩陣的某一格,那麼該路徑不能再次進入該格仔。利用回溯法的思想,除矩陣邊界上的格仔外,其它格仔都有四個相鄰的格仔,當矩陣中座標為 ro...
矩陣中的路徑(劍指offer 12)
設計乙個函式,用來判斷在乙個矩陣中是否存在一條包含某個字串所有字元的路徑,路徑可以從矩陣中任意一格開始,每一步可以在矩陣中向左 右 上 下各移動一格,如果一條路徑經過了矩陣中的某一格,那麼該路徑不能再次進入該格仔。例下 3 x 4的矩陣中包含一條字串 bfce 的路徑,但是矩陣中不包含 abfb 路...
劍指offer 12 矩陣中的路徑
判斷在乙個矩陣中是否存在一條包含某字串所有字元的路徑。路徑可以從矩陣中的任意乙個格仔開始,每一步可以在矩陣中向上下左右移動乙個格仔。如果一條路徑經過了矩陣中的某乙個格仔,則該路徑不能再進入該格仔。public class solution,private int rows private int c...