【Leetcode】python - [79] Word Search 個人解法筆記

整理 LeetCode #79 Word Search — DFS grid 遍歷、visited set、backtracking。

題目出處

79. Word Search

難度

medium

題目分類

Array, String, Backtracking, Depth-First Search, Matrix

2026-10-12 三刷

個人範例程式碼 - 三刷 (2026/10/12)

class Solution:
    def exist(self, board: list[list[str]], word: str) -> bool:
        m, n = len(board), len(board[0])
        directions = [(1,0),(0,1),(-1,0),(0,-1)]

        def dfs(i, j, visited, word_idx):
            if i < 0 or m <= i or j < 0 or n <= j or \
               board[i][j] != word[word_idx] or \
               (i, j) in visited:
                return False

            if word_idx == len(word)-1:
                return True

            visited.add((i, j))
            for di, dj in directions:
                if dfs(i+di, j+dj, visited, word_idx+1):
                    return True # found
            visited.remove((i, j)) # backtracking

            return False # not found

        for i in range(m):
            for j in range(n):
                if board[i][j] == word[0]:
                    if dfs(i, j, set(), 0):
                        return True

        return False

算法說明

大致可以拆成兩部分:起點搜尋、表格內搜尋。

  1. 起點搜尋:找到起始單字
  2. 表格內搜尋:根據上下左右進行 DFS 搜尋,留意重複(透過 visited 排除),留意 backtracking。

Time Complexity

O(mn3^L)

  1. m*n:起點搜尋
  2. 3^L:三個方向,扣掉來的方向 (會在 visited 裡面)

Space Complexity

O(L) # stack 裡面最長存字串長度

2026-09-30 二刷

個人範例程式碼 - 二刷 (2026/09/30)

class Solution:
    def exist(self, board: list[list[str]], word: str) -> bool:
        h, w = len(board), len(board[0])

        def dfs(r, c, word_idx, visited):
            if word_idx == len(word):
                return True

            if not (0 <= r < h) or not (0 <= c < w) or \
                (r, c) in visited or board[r][c] != word[word_idx]:
                return False

            visited.add((r, c))
            res =  dfs(r+1, c, word_idx+1, visited) or \
                   dfs(r-1, c, word_idx+1, visited) or \
                   dfs(r, c+1, word_idx+1, visited) or \
                   dfs(r, c-1, word_idx+1, visited)
            visited.remove((r, c)) # backtracking 先走錯分支回來再走, 要先刪除

            return res

        # find first word
        for r in range(h):
            for c in range(w):
                if board[r][c] == word[0] and \
                    dfs(r, c, 0, set()):
                    return True

        return False

算法說明

  1. DFS # 深度搜尋 與
  2. backtracking # 記得每次回頭要移除已經看過的路徑

的綜合題目

這題算是經典題型,找到第一個字之後進 DFS 進行上下左右搜尋,並用 visited 紀錄已經走過的路徑。

Time Complexity

O(mn*4^L)

  1. mn:矩陣大小,每格都要看
  2. 4^L:L 是文字長度,4 是 4 個方向,4^L 「表示每一個文字的 4 個方向都看的計算時間」 (再優化可以到 3^L,扣到來的方向)

Space Complexity

O(L) # 遞回最深就是文字 L 的長度

2022-04-27 一刷

個人範例程式碼 - 一刷 (2022/04/27)

DIRECTIONS = [
        (1, 0),
        (-1, 0),
        (0, 1),
        (0, -1)
        ]

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        if not board:
            return False

        # first point
        for i in range(len(board)):
            for j in range(len(board[0])):
                if board[i][j] == word[0] and self.dfs(board, word[1:], i, j, {(i,j)}):
                    return True
        return False # after all search

    def dfs(self, board, word, i, j, visited):
        # end of recursion
        if not word:
            return True

        # define and split
        for (dx, dy) in DIRECTIONS:
            next_x, next_y = i+dx, j+dy
            # print(next_point)
            if self.is_valid_point(next_x, next_y, board, visited, word[0]):
                visited.add((next_x, next_y))
                if self.dfs(board, word[1:], next_x, next_y, visited):
                    return True
                visited.remove((next_x, next_y)) # backtracking

        return False

# def dfs(self, board, word, start_point, visited)
#         # end of recursion
# if not word
#             return True

#         # define and split
# for (dx, dy) in DIRECTIONS
#             next_point = (start_point[0]+dx, start_point[1]+dy)
#             # print(next_point)
# if self.is_valid_point(next_point, board, visited, word[0])
#                 visited.add(next_point)
# if self.dfs(board, word[1:], next_point, visited)
#                     return True
#                 visited.remove(next_point) # backtracking

#         return False

    def is_valid_point(self, x, y, board, visited, word):
        if (x, y) in visited:
            return False
        r = len(board)
        c = len(board[0])
        return 0 <= x < r and 0 <= y < c and board[x][y] == word

最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解

算法說明

這題是學習矩陣內的四方向搜尋,類似題目可參考:

https://wongwongnotes.com/posts/algorithm-practice/data-structures/python-leetcode/leetcode-python-54/

不過這題目有個難點是很容易 TLE,在處理上我們需要稍微優化一下:

優化比較的項目長度

例如說可能不要比較整個 prefix,而是只比較單一個 word

不要使用 tuple 實作

我註解掉的部分是使用 tuple 實作的,概念上應該會更清楚,
但因為會影響到時間,後來取消掉註解後才沒有 TLE

input handling

當沒有 matrix 時,return False

Boundary conditions

搜尋到目標後,就可以 return True 了。
沿路上發現字母不對,就直接 return False

Reference

Licensed under CC BY-NC-SA 4.0
最後更新 Oct 12, 2026
使用 Hugo 建立
主題 Stack 由 Jimmy 設計