1. 程式人生 > 其它 >leetcode-矩陣中的路徑

leetcode-矩陣中的路徑

1. 題目描述

給定一個 m x n 二維字元網格 board 和一個字串單詞 word 。如果 word 存在於網格中,返回 true ;否則,返回 false 。

單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重複使用。

例如,在下面的 3×4 的矩陣中包含單詞 "ABCCED"(單詞中的字母已標出)

Leetcode連結:leetcode-矩陣中的路徑

示例1

輸入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
輸出:true

解題思路

本問題是典型的矩陣搜尋問題,可使用 深度優先搜尋(DFS)+ 剪枝 解決。

2. 深度優先搜尋+剪枝

  • 深度優先搜尋: 可以理解為暴力法遍歷矩陣中所有字串可能性。DFS 通過遞迴,先朝一個方向搜到底,再 回溯 至上個節點,沿另一個方向搜尋,以此類推。
  • 剪枝: 在搜尋中,遇到 這條路不可能和目標字串匹配成功 的情況(例如:此矩陣元素和目標字元不同、此元素已被訪問),則應立即返回,稱之為 [可行性剪枝] 。

3. DFS 解析:

遞迴引數: 當前元素在矩陣 board 中的行列索引 i 和 j ,當前目標字元在 word 中的索引 k
終止條件
返回 false : (1) 行或列索引越界 (2) 當前矩陣元素與目標字元不同 (3) 當前矩陣元素已訪問 。
返回 true : k = len(word) - 1 ,即字串 word** 已全部匹配**。
遞推工作

  • 標記當前矩陣元素: 將 board[i][j] 修改為 空字元 '' ,代表此元素已訪問過,防止之後搜尋時重複訪問。
  • 搜尋下一單元格: 朝當前元素的 上、下、左、右 四個方向開啟下層遞迴,使用 或 連線 (代表只需找到一條可行路徑就直接返回,不再做後續 DFS ),並記錄結果至 res 。
  • 還原當前矩陣元素: 將 board[i][j] 元素還原至初始值,即 word[k] 。

返回值: 返回布林量 res ,代表是否搜尋到目標字串。

4. 程式碼實現

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        def dfs(i, j, k):
            # 終止條件:遇到邊界,字母不匹配,當前元素已訪問過
            if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: 
		return False
            if k == len(word) - 1: return True
            # 置空,防止重複訪問
            board[i][j] = ''
            # 遞迴搜尋,滿足條件之一即可,
            res = dfs(i + 1, j, k + 1) or dfs(i - 1, j, k + 1) or dfs(i, j + 1, k + 1) or dfs(i, j - 1, k + 1)
            # 還原
            board[i][j] = word[k]
            return res

        for i in range(len(board)):
            for j in range(len(board[0])):
                if dfs(i, j, 0): return True
        return False

參考