开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情
1. 今日语录
层层递进,自上而下。
2. 题目
单词搜索
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用
3. 思路
对于这种二维结构的问题,通常都会想到回溯。 针对回溯性问题,可总结为2个要点。
以本题为例,
- 是否需要标记
对于全排列等回溯问题,标记数组当前位置为已经访问过的, 递归过来需要还原成初始值。
- 函数递归结束条件
这类条件往往不是唯一的,例如数组越界、当前位置的值不符合当前期望、 累计的结果达到 目标值target的 上限(例如数组长度已达到)。
对于单词搜索这题,我的思路是首先找到第一个元素,然后四个方向进行模拟 树的生成过程,同时记录生成次数。
当树的高度 顺利达到 目标单词的长度,即 返回true。
为了避免卡死在回溯过程,访问过的位置需要标记。
每次递归都有四个方向的探索,访问到目标字母 也返回true。 通过这样一层层的传递,1->2->3->... 自上而下,1能访问到2,2能访问到3...
最终,可以确定单词搜索是否成功。
var exist = function (board, word) {
const dfs = (i, j, k) => {
if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] !== word[k]) {
return false;
}
if (k === word.length - 1) {
return true;
}
board[i][j] = ''; //标记为已经找过了
let res = dfs(i - 1, j, k + 1) || dfs(i, j - 1, k + 1) ||
dfs(i + 1, j, k + 1) || dfs(i, j + 1, k + 1);
board[i][j] = word[k]; //结果得到,返回
return res;
}
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[0].length; j++) {
if (board[i][j] === word[0] && dfs(i, j, 0)) {
return true;
}
}
}
return false;
}
const board = [
["A", "B", "C", "E"],
["S", "F", "C", "S"],
["A", "D", "E", "E"]
]
const word = "ABCCED"
console.log(exist(board, word));
4. 关键字
回溯、层层递进