LeetCode 79. 單詞搜索 | Python

79. 單詞搜索


題目來源:https://leetcode-cn.com/problems/word-searchpython

題目


給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。數組

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

示例:微信

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

給定 word = "ABCCED", 返回 true
給定 word = "SEE", 返回 true
給定 word = "ABCB", 返回 false

提示:優化

  • board 和 word 中只包含大寫和小寫英文字母。
  • 1 <= board.length <= 200
  • 1 <= board[i].length <= 200
  • 1 <= word.length <= 10^3

解題思路


思路:深度優化搜索、回溯spa

首先看題意,題目中要求單詞必須按照字母順序,在給定的二維數組中,找到單詞。可經過相鄰單元格的字母組成,這裏【相鄰】包括橫向和縱向相鄰的單元格,這裏就涉及到一個偏移量的問題,可是同一個單元的字母不可以重複使用。code

先看下如何去實現搜索?首先咱們要先要對二維數組進行遍歷,要先找到跟單詞首字母相同的元素,這裏要注意,當找到這個元素時,要先進行標記,由於題意要求字母不能重複使用。blog

當找到這個元素時,從當前元素的位置開始進行搜索,須要往四個方位進行搜索,看看相鄰的單元格元素是不是單詞的下一個字母,這裏分爲兩種狀況:leetcode

  • 可以匹配時,從這個元素繼續進行搜索
  • 不能匹配時,返回 False,這裏要進行回溯

當全部的字母徹底匹配時,則返回 True。rem

具體的實現代碼以下。

代碼實現


class Solution:
    directions = [(1, 0), (0, -1), (-1, 0), (0, 1)]

    def exist(self, board: List[List[str]], word: str) -> bool:
        if len(board) == 0:
            return False
        
        # 四個方位偏移量
        

        rows = len(board)
        cols = len(board[0])

        # 這裏用以標記元素是否使用
        # False 表示未使用
        # True 表示已使用
        marked = [[False for _ in range(cols)] for _ in range(rows)]

        # 先遍歷,
        for row in range(rows):
            for col in range(cols):
                    # 當找到全部元素時返回 True
                    if self._search(row, col, board, word, 0, marked):
                        return True
        return False

    def _search(self, i, j, board, word, index, marked):
        # 終止條件
        if index == len(word) - 1:
            return board[i][j] == word[index]

        # 只有匹配了才繼續搜索
        if board[i][j] == word[index]:
            # 這裏先標記元素,若是搜索不成功的狀況下,解除標記
            marked[i][j] = True
            # 四個方位搜索
            for dx, dy in self.directions:
                nrow = i + dx
                ncol = j + dy

                # 限定邊界,
                # 搜索時找相鄰未使用過的元素
                if 0 <= nrow < len(board) and 0 <= ncol < len(board[0]) and not marked[nrow][ncol] and self._search(nrow, ncol, board, word, index + 1, marked):
                    return True
            # 釋放標記
            marked[i][j] = False
        return False

實現結果


實現結果

總結


  • 使用深度優先搜索 + 回溯的思路,解決此題;
  • 首先定位單詞首元素,找到對應的位置以後,由此從四個方位繼續搜索;
  • 搜索的同時,要先標記當前元素爲已使用,防止後面定位的元素搜索時重複使用;
  • 若是某個搜索路線未找到單詞時,要進行回溯,將這次標記的元素所有釋放。

歡迎關注微信公衆號《書所集錄》
相關文章
相關標籤/搜索