79. 單詞搜索
題目來源:https://leetcode-cn.com/problems/word-search
題目
給定一個二維網格和一個單詞,找出該單詞是否存在於網格中。
單詞必須按照字母順序,通過相鄰的單元格內的字母構成,其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。
示例:
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
解題思路
思路:深度優化搜索、回溯
首先看題意,題目中要求單詞必須按照字母順序,在給定的二維數組中,找到單詞。可通過相鄰單元格的字母組成,這里【相鄰】包括橫向和縱向相鄰的單元格,這里就涉及到一個偏移量的問題,但是同一個單元的字母不能夠重復使用。
先看下如何去實現搜索?首先我們要先要對二維數組進行遍歷,要先找到跟單詞首字母相同的元素,這里要注意,當找到這個元素時,要先進行標記,因為題意要求字母不能重復使用。
當找到這個元素時,從當前元素的位置開始進行搜索,需要往四個方位進行搜索,看看相鄰的單元格元素是否是單詞的下一個字母,這里分為兩種情況:
- 能夠匹配時,從這個元素繼續進行搜索
- 不能匹配時,返回 False,這里要進行回溯
當所有的字母完全匹配時,則返回 True。
具體的實現代碼如下。
代碼實現
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
實現結果
總結
- 使用深度優先搜索 + 回溯的思路,解決此題;
- 首先定位單詞首元素,找到對應的位置之后,由此從四個方位繼續搜索;
- 搜索的同時,要先標記當前元素為已使用,防止后面定位的元素搜索時重復使用;
- 如果某個搜索路線未找到單詞時,要進行回溯,將此次標記的元素全部釋放。
歡迎關注微信公眾號《書所集錄》