每日一题- day 11

71 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

1. 今日语录

层层递进,自上而下。

2. 题目

单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用

3. 思路

对于这种二维结构的问题,通常都会想到回溯。 针对回溯性问题,可总结为2个要点。

以本题为例,

  1. 是否需要标记

对于全排列等回溯问题,标记数组当前位置为已经访问过的, 递归过来需要还原成初始值。

  1. 函数递归结束条件

这类条件往往不是唯一的,例如数组越界、当前位置的值不符合当前期望、 累计的结果达到 目标值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. 关键字

回溯、层层递进