[LeetCode79.单词搜索] | 刷题打卡

985 阅读2分钟

前言

​ 大三下学期了,既然已经准备工作的话,就要开始自己的刷题之旅了。目前自己正在看剑指offer里面的题目。已经刷了将近30道题,但是现在再去看前几天自己做出来的题依然不能完整的写出来。所以我觉得应该停下来去复习一下前面的题目,整理一下做题的套路。所以把自己的刷题心得和思考写在这里,与大家分享。

题目描述

给定一个二维网格和一个单词,找出该单词是否存在于网格中。

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

难度:中等

示例:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false

提示:

board 和 word 中只包含大写和小写英文字母。
1 <= board.length <= 200
1 <= board[i].length <= 200
1 <= word.length <= 10^3

解题思路

  1. ​ 二维网格中查找一个单词,首先应该先在这个二维数组中找到这个单词的首字母。然后对这个二维数组进行深度优先搜索(DFS)。

  2. DFS函数的参数应该是此时二维数组的坐标i,j和判断第几个单词的index。在DFS中应该首先保证i,j的值不超过二维数组的边界。否则返回false。

    if(i < 0 || i >= board.length || j >= board[0].length) return false;
    
  3. 判断board[i][j]是否等于word[index]。如果等于的话就把word[index]赋值给一个变量tmp,然后把board[i][j赋值为0表示这个元素已经使用过了。然后就是对二维数组中这个元素的上下左右进行试探,看是否与word的下一个字母符合。如果匹配到就继续递归,否则就返回false。当上下左右都查找完后,应该撤销二维数组中的修改。因为一个字母只能用一次。

    AC代码

    /*
     * @lc app=leetcode.cn id=79 lang=javascript
     *
     * [79] 单词搜索
     */
    
    // @lc code=start
    /**
     * @param {character[][]} board
     * @param {string} word
     * @return {boolean}
     */
    var exist = function (board, word) {
        for (let i = 0; i < board.length; i++) {
            for (let j = 0; j < board[0].length; j++) {
                //寻找第一个符合条件的字符
                if (word[0] === board[i][j]) {
                    if (dfs(i, j, 0)) {
                        return true;
                    }
                }
            }
        }
        return false;
    
        function dfs(i, j, index) {
            if (i < 0 || i >= board.length || j >= board[0].length) return false;
            let flag = false;
            if (board[i][j] === word[index]) {
                if (index === word.length - 1) {
                    return true;
                }
                let tmp = board[i][j];
                board[i][j] = '0';
                flag = flag || dfs(i + 1, j, index + 1);
                flag = flag || dfs(i - 1, j, index + 1);
                flag = flag || dfs(i, j + 1, index + 1);
                flag = flag || dfs(i, j - 1, index + 1);
                board[i][j] = tmp; 
            }
            return flag;
    
        }
    };
    
    // @lc code=end
    board = [
        ['A', 'B', 'C', 'E'],
        ['S', 'F', 'C', 'S'],
        ['A', 'D', 'E', 'E']
    ]
    
    let word = "ABCCED";
    

    总结

    ​ 回溯算法就是暴力枚举,就是一个一个的去试。如果列举到一半不符合条件,就及时剪枝,并把之前做的选择撤销。同时需要递归可能出现的所有情况。也要注意结束递归的条件,本题中的结束条件分别是查完二维数组也没找到首字母,i,j小于二维数组的边界,index的值和word字符串的长度相同。

image.png 本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情