剑指 Offer 12. 矩阵中的路径

207 阅读2分钟

剑指 Offer 12. 矩阵中的路径

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

1、题目📑

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

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

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

img

实例1

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"

输出:true

实例2

输入:board = [["a","b"],["c","d"]], word = "abcd"

输出:false

说明:

  • 1 <= board.length <= 200
  • 1 <= board[i].length <= 200
  • boardword 仅由大小写英文字母组成

注意:本题与主站 79 题相同:leetcode-cn.com/problems/wo…

2、思路🧠

方法一:DFS 深度优先遍历

回溯算法实际上一个类似枚举的搜索尝试过程,换句话说就是一个个去试,枚举所有可能出现的情况,解这道题也是通过一个个去试的方法进行解题。

image-20220425222931651

看到他是从矩形中的某一个位置开始向上下左右四个方向寻找,这个点可以是矩形中的任何一个点,所以代码的大致轮廓应该能写出来,也就是遍历矩形所有的点,然后从这个点开始进行4个方向探索,因为是二维数组,所以有两个for循环,代码如下

for(int i = 0; i < board.length; i++) {
    for(int j = 0; j < board[0].length; j++) {
        if(dfs(board, words, i, j, 0)) {
            return true;
        }
    }
}

其实这个代码的关键就是dfs该如何去写

  1. 递归结束条件
    • 也就是所说的边界条件,超过左边界、右边界、上边界、下边界
    • 还需要判断无法匹配的情况
    • 如果已经扫描到word尾部,则必然是找到了
  2. 递归回溯:
    • 接下来就是重头戏了,各位小伙伴们
    • 上下左右4个方向中,只要有一个能查找到,就返回true;
    • 但是在进行方向的判断时候,需要将该店进行标记,代表此元素已访问过,否则就会出现不知道现在判断到那个点,那些点已经遍历过了的问题
    • 返回之前必须要将该标记的点值为初始情况,也就是复原,这样做的目的是为了回溯。
  3. 返回值
    • 返回布尔量,代表是否搜索到目标字符串。

废话少说~~~~~上代码!

3、代码👨‍💻

第一次commit AC

class Solution {
    public boolean exist(char[][] board, String word) {
        char [] words = word.toCharArray();
        for(int i = 0; i < board.length; i++) {
            for(int j = 0; j < board[0].length; j++) {
                if(dfs(board, words, i, j, 0)) {
                    return true;
                }
            }
        }
        return false;
    }

    public boolean dfs(char [][]board, char []word,int i,int j, int index) {
        //递归结束条件
        if(i<0 || j<0 || i >= board.length || j >= board[0].length || board[i][j] != word[index]) {
            return false;
        }
        //如果已经扫描到word尾部,则必然是找到了
        if(word.length - 1 == index) {
            return true;
        }
        //将当前位置进行标记
        board[i][j] = '.';
        boolean res = dfs(board, word, i + 1, j, index + 1) || dfs(board, word, i - 1, j, index + 1) ||
                      dfs(board, word, i, j + 1, index + 1) || dfs(board, word, i, j - 1, index + 1);
                      
        //还原状况,进行回溯
        board[i][j] = word[index];
        return res;
    }
}

时间复杂度:O(3KMN) 搜索中每个字符有上、下、左、右四个方向可以选择,舍弃回头的方向,剩余3个方向,时间复杂度为O(3K),其次矩阵中共有MN个节点,所以时间复杂度为O(3KMN)

空间复杂度:O(K)

image-20220425221240852

4、总结

该题目的是对搜索和回溯的思想进行练习,这个题的关键点在于dfs函数的编写,因为每一个起点都需要向它的4个方向进行查找,所以可以把它想象为一棵4叉树,就是每个节点有4个子节点(孩子),而树的遍历我们最容易想到的就是递归,自然就明白了递归和回溯。

❤️‍来自专栏《LeetCode基础算法题》欢迎订阅❤️‍

厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。

对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!

原题链接:剑指 Offer 12. 矩阵中的路径 - 力扣(LeetCode) (leetcode-cn.com)