描述
在给定的 2D 平面 board 中搜索单词 word,可以在垂直相邻和水平相邻方向进行深度搜索,如果找到返回 True,否则返回 False。
1 | board = |
测试用例
1 | board = |
分析
这是一个经典的 DFS 问题,对于一个坐标 (x, y)
可以往四个方向进行搜索,分别是 (x+1, y)
, (x-1, y)
, (x, y+1)
, (x, y-1)
。四个方向只要有一个方向搜索成功即可,搜索成功的条件是搜索深度 d == len(word)-1
。而搜素失败的原因有很多:
- (x, y) 出界;
- (x, y) 已经使用过(题目要求每个坐标只能使用一次);
- 当前的 (x, y) 对应的值和 word[d] 不相等。
根据以上分析,构造 dfs 函数需要的参数有 x, y 和 d,其中 d 表示搜索的深度。此外,还需要一个保存搜索过的坐标的辅助变量,这个变量可以放在全局。考虑搜索失败的情况,代码如下:
1 | visited = set() |
如果当前坐标 (x, y) 满足条件 board[x][y] == word[d]
且 d == len(word) - 1
则搜索成功,代码如下
1 | visited = set() |
否则继续往当前坐标的四个方向深入搜索,同时将当前坐标加入到 visited 中,表示当前坐标已经访问过,
1 | visited = set() |
如上,代码基本结构已经完成,大部分测试已经通过。但是, 考虑具有回溯情况的 Case 2 ,以上代码会失。这是因为如果坐标 (x,y) 的某个方向深入搜索多个步骤后失败,最终还会回到 (x, y) 上进行下一个方向的尝试,可是在进行下一个方向搜索时,上次的失败搜索并没有释放搜索过的坐标,导致有些坐标在本次搜索不能被访问,最终搜索失败。 所以,对于当前坐标的搜索,如果四个方向都搜索失败,则需要释放当前的 (x, y),即 回溯。如下:
1 | visited = set() |
代码实现
根据如上分析,代码实现如下(实现使用 used 数组保存访问过的坐标,和用集合 visited 功能一致):
1 | class Solution: |
改进:
如上代码使用额外空间来记录访问过的坐标,以避免重复访问,有个技巧可以使用 O(1) 的空间记录访问过的节点。我们只需要用一个特殊符号如 “#” 将访问过的坐标值替换,勾勒出访问路径,并在当前坐标搜索完成后将原来的值替换回来即可。如下:
1 | class Solution: |