# **Leetcode筆記(Word Search)** :::info :information_source: 題目 : Word Search, 類型 : graph , 等級 : medium 日期 : 2023/03/02,2023/05/17,2023/07/11,2023/12/01,2024/04/04,2025/02/20 ::: ### 嘗試 2023/05/17,判斷錯誤條件要放上面 ```python 条件判断顺序错误:在 dfs 函数中,你应该首先检查边界条件, 然后再检查字符匹配和访问状态。 将边界条件判断放在了字符匹配判断之后, 这会导致出现越界或访问重复位置的情况。 錯誤 : if board[r][c] != word[i] or r < 0 or r >= m or c < 0 or c >= n or (r, c) in visited class Solution: def exist(self, board: List[List[str]], word: str) -> bool: m, n = len(board), len(board[0]) dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)] visited = set() def dfs(r, c, i): if i == len(word): return True # 條件不符 if r < 0 or r >= m or c < 0 or c >= n or board[r][c] != word[i] or (r, c) in visited: return False visited.add((r, c)) for dr, dc in dirs: nr, nc = r + dr, c + dc # 如果把r和c的範圍限制條件放在這裡 # 會使得board = "a", word = "a"這種例子無法通過 # 但如果放上面進到i == len(word)就會通過了 if dfs(nr, nc, i + 1): return True # 會跑到這邊就代表dfs沒有回傳True # 要回頭是其他條路 visited.remove((r, c)) return False for r in range(m): for c in range(n): if dfs(r, c, 0): return True return False ``` 2023/07/11 需要**在遞迴呼叫dfs()時,加上if dfs(),因為如果其中一個一層達成上面return True的條件,那後面在遞迴stack的 皆無條件return True** 最後**如果這條路徑走不通,那就需要remove((r, c)),如果有兩層以上的遞迴路徑,remove會使得退回上一層時,visited內裝的是正常的路徑** ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] visited = set() def dfs(r, c, i, visited): if i == len(word): return True if r < 0 or c < 0 or r >= len(board) or c >= len(board[0]) or board[r][c] != word[i] or (r, c) in visited: return visited.add((r, c)) for dr, dc in dirs: nr, nc = r + dr, c + dc # 如果其中一個一層達成上面return True的條件 # 那後面在遞迴stack的 皆無條件return True if dfs(nr, nc, i + 1, visited): return True visited.remove((r, c)) return for r in range(len(board)): for c in range(len(board[0])): if dfs(r, c, 0, visited): return True return False ``` 2023/12/01 ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: n, m = len(board), len(board[0]) visited = set() dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] def dfs(r, c, i): if i == len(word): return True if r < 0 or c < 0 or r >= n or c >= m or (r, c) in visited or board[r][c] != word[i]: return False visited.add((r, c)) for dr, dc in dirs: nr, nc = r + dr, c + dc if dfs(nr, nc, i + 1): return True visited.remove((r, c)) return False for r in range(n): for c in range(m): if dfs(r, c, 0): return True return False ``` 2024/04/04 ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: m, n = len(board), len(board[0]) visited = set() dirs = [(0, 1), (0, -1), (1, 0), (-1, 0)] def dfs(r, c, i): if i == len(word): return True if r < 0 or r >= m or c < 0 or c >= n or (r, c) in visited or board[r][c] != word[i]: return False visited.add((r, c)) for dr, dc in dirs: nr, nc = r + dr, c + dc if dfs(nr, nc, i + 1): return True visited.remove((r, c)) return for r in range(m): for c in range(n): if dfs(r, c, 0): return True return False ``` 2025/02/20 ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: self.n, self.m = len(board), len(board[0]) self.dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] self.visited = set() self.board, self.word = board, word for r in range(self.n): for c in range(self.m): if self.dfs(r, c, 0): return True return False def dfs(self, r, c, i): if i == len(self.word): return True if r < 0 or r >= self.n or c < 0 or c >= self.m or self.board[r][c] != self.word[i] or (r, c) in self.visited: return self.visited.add((r, c)) for dr, dc in self.dirs: nr, nc = r + dr, c + dc if self.dfs(nr, nc, i + 1): return True self.visited.remove((r, c)) return ``` --- ### **優化** 時間複雜度: - 在最壞的情況下,我們需要遍歷整個二維字符矩陣,因此時間複雜度為 O(rows * cols),其中 rows 是矩陣的行數,cols 是矩陣的列數。 - 在每個遍歷過程中,我們可能需要遞迴調用 `dfs` 函數,該函數的時間複雜度與單詞長度相關,即 O(word_length)。 - **總體時間複雜度為 O(rows * cols * word_length)**。 空間複雜度: - **在最壞的情況下(當word等於整個matrix上面的所有數字)**,當遞迴深度達到最大值時,堆疊空間的最大需求是 O(rows * cols)。 - `visited` 集合用於記錄已訪問的位置,其大小取決於二維字符矩陣的大小,最大情況下是 O(rows * cols)。 - 總體空間複雜度為 O(rows * cols)。 ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: row, col = len(board), len(board[0]) path = set() def dfs(r, c, i): # i為word中第幾個 if i == len(word): return True if (r < 0 or c < 0 or r >= row or c >= col or word[i] != board[r][c] or # 字母對不上 (r, c) in path): # 已找到過 return False # 也可以只打return(也就是return None) # 跳回呼叫它的起點 path.add((r, c)) # 開始找到第一個會經過這裡 # 若有任一一個dfs()執行,則res會收到true res = (dfs(r + 1, c, i + 1) or dfs(r - 1, c, i + 1) or dfs(r, c + 1, i + 1) or dfs(r, c - 1, i + 1)) # 上面找到的那點鄰近都沒有下一個點 代表不是真正的正確點 path.remove((r, c)) return res # True或False # 如果是False 則會回去下面 跑下一個迴圈 for r in range(row): for c in range(col): if dfs(r, c, 0): # 從word中第一個字開始 # 也只找第一個字 # 若此指令為true,也就是上面回傳true return True return False ``` --- **:warning: 錯誤語法** :::warning 換行 : 在一行末尾加上‘\’ 從程式碼中清楚的判斷這個輸出是bool還是list還是int等等 ::: **:thumbsup:學習** :::success 函數中若有return就會跳出該函數,不會執行下面的程式碼 若是return沒有給資料,也會跳回到呼叫該函式的區塊,回傳值的結果是 None 集合不會包含重複的資料 set.add(value) set.remove(value) 檢查元素是否在集合 : r, c in set ::: **思路** **講解連結** https://www.youtube.com/watch?v=pfiQ_PS1g8E Provided by. NeetCode ###### tags: `graph` `medium` `leetcode`