60.单词搜索(学习)
给定一个 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 仅由大小写英文字母组成
解析:
一、边界条件和字符匹配检查:
1.如果当前位置超出网格边界、已被访问过、或当前单元格的字符与 word[index] 不匹配,则返回 false。
二、匹配完成检查:
1.如果 index 已经等于 word.length - 1(即已经匹配完整个 word),则返回 true。
三、标记当前位置为已访问:
1.将当前位置标记为已访问,以避免重复访问。
四、向四个方向搜索:
1.定义四个方向(上、下、左、右)的偏移量数组 directions。
2.遍历这四个方向,对每个方向执行 dfs 递归调用,传入新的行和列索引(通过当前索引加上方向的偏移量得到),以及 index + 1(因为已经匹配了一个字符)。
3.如果在任何一个方向的搜索中找到了匹配的路径(即 dfs 返回 true),则立即返回 true。
五、回溯:
1.如果所有方向的搜索都失败了(即没有找到匹配的路径),则需要回溯,即将当前位置重新标记为未访问,以便其他路径可以访问它。
2.注意:这里的回溯是通过在 dfs 函数返回前将 visited[row][col] 设置为 false 来实现的。
var exist = function (board, word) {
const rows = board.length;
const cols = board[0].length;
const visited = Array.from({ length: rows }, () => Array(cols).fill(false));
// 辅助函数,用于进行深度优先搜索
function dfs(row, col, index) {
// 检查边界条件和字符匹配
if (
row < 0 ||
row >= rows ||
col < 0 ||
col >= cols ||
visited[row][col] ||
board[row][col] !== word[index]
) {
return false;
}
// 如果已经匹配完整个单词,则返回 true
if (index === word.length - 1) {
return true;
}
// 标记当前位置为已访问
visited[row][col] = true;
// 继续向四个方向搜索
const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]];
for (const [dx, dy] of directions) {
if (dfs(row + dx, col + dy, index + 1)) {
return true;
}
}
// 回溯,重置当前位置为未访问
visited[row][col] = false;
return false;
}
// 遍历二维网格的每个位置,作为搜索的起点
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (dfs(i, j, 0)) {
return true;
}
}
}
return false;
};