跳到正文
第 79 题中等

单词搜索

Word Search

在网格中判断是否存在一条路径,按顺序拼出给定单词;路径只能上下左右走,不能重复用格。

在力扣中练习

题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

 

示例 1:

输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCCED"
输出:true

示例 2:

输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "SEE"
输出:true

示例 3:

输入:board = [['A','B','C','E'],['S','F','C','S'],['A','D','E','E']], word = "ABCB"
输出:false

 

提示:

  • m == board.length
  • n = board[i].length
  • 1 <= m, n <= 6
  • 1 <= word.length <= 15
  • board 和 word 仅由大小写英文字母组成

 

进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?

解题思路

主解法

DFS + 原地标记

匹配一个字符就占住格子,失败时恢复

从每个格子出发尝试匹配 word[0],匹配成功就向四个方向递归匹配下一个字符。

已经走过的格子不能在当前路径中再次使用。最省空间的做法是把它临时改成 '#',递归返回时再恢复原字符;这样不需要额外的 visited 矩阵。

分步图解

匹配第 0 个字符 H,进入 (1,0)。

k
0
单词 HORSE
0
1
2
3
0
W
A
T
E
1
H0
O
R
S
2
L
I
N
E
3
D
R
A
M
已匹配的格子标绿色并记录顺序;同一格不能在一条路径里重复使用。
已匹配的字符
H
目标
HORSE
1 / 4
从 H 开始依次向右匹配 O、R、S,每走一步都标记当前格。

自拟网格中的 HORSE 需要向右走三步、再向上拐一次。方向顺序不重要,但每个方向失败后都必须恢复当前格,否则其他路径会被错误地挡住。

分步图解

匹配第 3 个字符 S,进入 (1,3)。

k
3
单词 HORSE
0
1
2
3
0
W
A
T
E
1
H0
O1
R2
S3
2
L
I
N
E
3
D
R
A
M
已匹配的格子标绿色并记录顺序;同一格不能在一条路径里重复使用。
已匹配的字符
H
O
R
S
目标
HORSE
1 / 3
S 的右边越界,只能向上到 E;错误分支返回后标记会恢复。

每个起点做一次 DFS,单次最多 4^L 条路径,总时间 O(m·n·4^L),递归深度 O(L)。

时间 O(m·n·4^L)空间 O(L)

易错点

  • 失败后忘记恢复字符:后续起点无法使用这一格。
  • 只向两个方向搜索:漏掉向上/向左的路径。
  • 没有越界检查就取 board[r][c]:会访问非法内存。
  • 认为起点必须在 (0,0):单词可以从任意位置开始。
对照解法

DFS + visited 矩阵

单独开一个布尔矩阵记录当前路径

逻辑等价,额外 O(m·n) 空间;原地标记版把访问状态复用到了棋盘上。

如果不想修改输入棋盘,可以开一个 used 矩阵,进入格子时设为 true,回退时设为 false。

它的可读性更好:棋盘数据和访问状态分离,调试时能直接看到哪些格子在当前路径上。代价是 O(m·n) 额外空间。

当棋盘不能被修改,或者需要同时保留多个搜索状态时,visited 矩阵更合适;否则原地标记更省空间。

  1. 1建立与棋盘同尺寸的 used。
  2. 2进入格子前检查 used。
  3. 3递归前置 true,失败后置 false。
  4. 4其余与原地标记相同。
时间 O(m·n·4^L)空间 O(m·n + L)

易错点

  • used 只置 true 不恢复:所有路径共享了错误的访问历史。
  • 把 used 按值传参:每次递归复制整张矩阵,复杂度爆炸。

代码与演示

主解法配有图解;对照解法用于比较思路、复杂度或实现方式。

演示输入board = [["W","A","T","E"],["H","O","R","S"],["L","I","N","E"],["D","R","A","M"]],word = "HORSE"

要从网格中找 "HORSE",可以向上下左右走,但不能斜走或重复经过同一格。

单词 HORSE
0
1
2
3
0
W
A
T
E
1
H
O
R
S
2
L
I
N
E
3
D
R
A
M
已匹配的格子标绿色并记录顺序;同一格不能在一条路径里重复使用。
已匹配的字符
空
目标
HORSE
1 / 3
查看 C++ 代码

延伸阅读

  • 网格搜索的“已访问”是路径级状态,不是全局状态;回溯时必须撤销。
  • 如果单词很长,可以先统计字符频次,棋盘不足时直接返回 false。