【牛客 - 剑指offer】JZ12 矩阵中的路径 深度优先搜索DFS Java实现


剑指offer题解汇总 Java实现

https://blog.csdn.net/guliguliguliguli/article/details/126089434

本题链接

知识分类篇 - 回溯 - JZ12 矩阵中的路径

题目

在这里插入图片描述

题目主要信息

  • 矩阵中上下左右随便移动,找到给定字符串的路径
  • 访问可以重复,但是作为路径不能往回走

方案 深度优先搜索

递归与回溯

递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此,递归过程,最重要的就是查看能不能将原本的问题分解成更小的子问题,这是使用递归的关键。

如果是线性递归,子问题直接回到父问题不需要回溯,但是如果是树型递归,父问题有很多分支,需要回到父问题,再进入父问题的另一个子问题。因此,回溯是指在递归过程中,从某一分支的子问题回到父问题,进入父问题的另一个子问题分支,因为有时候进入第一个子问题的时候,修改过一些变量,因此回溯的时候会要求改回父问题时的状态才能进入另一个子问题分支。

来自陈玉福老师《算法讲义》:
回溯法采用深度优先搜索的方式,朝纵深方向搜索,直至达到问题的一个可行解,或经判断不会达到问题的可行解或最优解时,停止向前搜索,并沿原路返回到该路径上最后一个还可扩展节点。然后,从该节点出发朝新的方向纵深搜索。

思路

首先在二维矩阵中找到起点,然后检查起点的上、下、左、右四个方向,看是否有满足条件的路径,有的话,则不断深入

在dfs(int x,int y,int pos)方法中,pos表示字符串的下标,即当前遍历到字符串的第几个位置

  • 如果已经找到一条路线,return
  • 如果成功找到了第一条路线,则设置isFind遍历为true(不会再继续查找下去),return
  • 如果坐标越界,return
  • 如果当前位置已经访问过了,return
  • 如果当前访问的x,y位置的字符刚好与字符串中pos位置上的字符一致,则以该位置为中心,继续检查上、下、左、右四个方向

代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param matrix char字符型二维数组
     * @param word   string字符串
     * @return bool布尔型
     */

    private char[][] map;
    private boolean[][] vis;
    private String way;
    private boolean isFind;

    public boolean hasPath(char[][] matrix, String word) {

        map = matrix;

        vis = new boolean[matrix.length][matrix[0].length];

        way = word;


        //获得字符串的第一个字符,找到起始位置
        char start = word.charAt(0);
        for (int i = 0; i < matrix.length; i++) {

            for (int j = 0; j < matrix[i].length; j++) {

                //找到起始位置
                if (matrix[i][j] == start) {

                    isFind = false;
                    
                    //初始化vis二维数组是false
                    for (int k = 0; k < matrix.length; k++) {
                        Arrays.fill(vis[k], false);
                    }
                    dfs(i, j, 0);

                    if (isFind) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private void dfs(int x, int y, int pos) {
        //已经找到路线
        if (isFind) {
            return;
        }
        //找到了路线
        if (pos == way.length()) {
            isFind = true;
            return;
        }
        //越界,直接返回
        if (x >= map.length || x < 0 || y >= map[0].length || y < 0) {
            return;
        }

        //已经访问过
        if (vis[x][y]) {
            return;
        }

        //当前x,y位置的字符刚好是string字符串中的,则遍历它的上下左右方向
        if (map[x][y] == way.charAt(pos)) {
            vis[x][y] = true;
            //向下
            dfs(x + 1, y, pos + 1);

            //向上
            dfs(x - 1, y, pos + 1);

            //向右
            dfs(x, y + 1, pos + 1);

            //向左
            dfs(x, y - 1, pos + 1);

            vis[x][y] = false;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值