DFS! 给我冲

No.剑指 Offer 12 矩阵中的路径

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

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

 

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

 

示例 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 题相同:https://leetcode-cn.com/problems/word-search/

思路分析

dfs意思就是深度优先搜索
其实,dfs是最像人的平常思维的一种方法,就是一个一个来匹配
可以想象,如果你来人为判断这道题,该怎么判断呢?

  1. 首先在board里找到一个和word中的第个字符相等的字符a(变量名)
  2. 从a字符的四个方向(上下左右)找到和word中第个字符相等的字符b(变量名)
  3. 再从b字符的三个方向(除了刚刚从a转移过来的那一方向)找到word第三个字符相等的字符(变量名)
  4. …(中途如果有不匹配,则退回到上一个字符,再从其他方向尝试)
  5. 最后判断到最后一个字符,然后成功找到,就可以啦

注:正如上述的3,在判断过程中,不能往之前判断过的路径判断,所以判断过的地方我们就暂时置为一个谁都不可能相等的标记,会在如下代码中体现出来。

所以dfs往往是最好理解的一类题型,给熟练的大佬写的话,可能思考过程都不要,就是对着键盘一顿敲,几分钟就写完了。如果感觉将这种简单的思维变成代码比较困难,不要紧,说明题目练的还不够,多看几遍优秀的代码多敲几遍,也自然就会了(当然我写的挺垃圾的,提供一种思路吧)

Java代码

class Solution {
    boolean flag = false;
    int[] m = new int[]{1, 0, -1, 0};
    int[] n = new int[]{0, 1, 0, -1};

    public boolean exist(char[][] board, String word) {
        int row = board.length;
        int col = board[0].length;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (flag) {
                    break;
                }
                dfs(board, word, row, col, i, j, 0);
            }
        }
        return flag;
    }

    private void dfs(char[][] board, String word, int row, int col, int i, int j, int temp) {
        /* 剪枝 */
        if (flag) {
            return;
        }
        /* 防越界 */
        if (!(i >= 0 && i < row && j >= 0 && j < col)) {
            return;
        }
        /* 不相等的回退 */
        if (board[i][j] != word.charAt(temp)) {
            return;
        }
        /* 最终情况正确的处理 */
        if (temp == word.length() - 1) {
            flag = true;
            return;
        }
        /* 将该点暂时打上标记 */
        char c = board[i][j];
        board[i][j] = '*';
        for (int k = 0; k < 4; k++) {
            dfs(board, word, row, col, i + m[k], j + n[k], temp + 1);
        }
        /* 解除标记 */
        board[i][j] = c;
    }
}

喜欢的话点个赞呗~
嚯嚯嚯

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值