📝 题目描述

题目链接单词搜索

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

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

示例:

示例 1:

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

示例 2:

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

示例 3:

1
2
输入: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 仅由大小写英文字母组成

💡 解题思路

方法一:回溯

很经典的回溯题目。

从任意一个格子开始探索,然后如果匹配字母成功,就递归继续探索。

如果在递归时发现单词的字母编号和单词长度相等,就返回 true

值得注意的是,由于题目要求我们不能重复使用一个格子,所以这里要设置一个 visited 数组,因此如果匹配失败,记得将数组复原。

🔧 代码实现

1、回溯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m = board.size(), n = board[0].size();
vector<vector<bool>> visited(m, vector<bool>(n, false));

for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 直接从 index 0 开始 DFS 搜索
if (dfs(board, word, 0, i, j, visited)) {
return true;
}
}
}
return false;
}

private:
bool dfs(vector<vector<char>>& board, const string& word, int index, int i, int j, vector<vector<bool>>& visited) {
// 1. 递归的终止条件:单词已经全部匹配完
if (index == word.size()) return true;

// 2. 统一判断越界、是否已访问、字符是否匹配
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() ||
visited[i][j] || board[i][j] != word[index]) {
return false;
}

// 3. 标记当前节点为已访问
visited[i][j] = true;

// 4. 探索四个方向 (只要有一个方向通了,就会一路返回 true)
bool res = dfs(board, word, index + 1, i + 1, j, visited) ||
dfs(board, word, index + 1, i - 1, j, visited) ||
dfs(board, word, index + 1, i, j + 1, visited) ||
dfs(board, word, index + 1, i, j - 1, visited);

// 5. 核心:状态回溯!将当前节点重新标记为未访问,不影响其他路径的探索
visited[i][j] = false;

return res;
}
};

📊 复杂度分析

1、回溯

  • 时间复杂度
  • 空间复杂度

🎯 总结

  • 核心思想: