• 【java刷算法】牛客—剑指offer4DFS与BFS两种思路的碰撞,一起来练习吧



    ✨今日二剑

    JZ12 矩阵中的路径

    JZ13 机器人的运动范围



    JZ12 矩阵中的路径

    题目描述

    在这里插入图片描述

    思路详解

    本题我们用回溯算法解决。
    我们看到他是从矩形中的一个点开始往他的上下左右四个方向查找,这个点可以是矩形中的任何一个点,就是遍历矩形所有的点,然后从这个点开始往他的4个方向走,因为是二维数组,所以有两个for循环。
    我们接下来写一个 dfs 方法,对其控制判断和方向的转变。
    详细见注释哦!!!

    代码与结果

    import java.util.*;
    
    
    public class Solution {
        /**
         * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
         *
         * 
         * @param matrix char字符型二维数组 
         * @param word string字符串 
         * @return bool布尔型
         */
       public boolean hasPath(char[][] matrix, String word) {
        char[] words = word.toCharArray();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[0].length; j++) {
                //从[i,j]这个坐标开始查找
                if (dfs(matrix, words, i, j, 0))
                    return true;
            }
        }
        return false;
    }
     
    boolean dfs(char[][] matrix, char[] word, int i, int j, int index) {
        //边界的判断,如果越界直接返回false。index表示的是查找到字符串word的第几个字符,
        //如果这个字符不等于matrix[i][j],说明验证这个坐标路径是走不通的,直接返回false
        if (i >= matrix.length || i < 0 || j >= matrix[0].length || j < 0 || matrix[i][j] != word[index])
            return false;
        //如果word的每个字符都查找完了,直接返回true
        if (index == word.length - 1)
            return true;
        //把当前坐标的值保存下来,为了在最后复原
        char tmp = matrix[i][j];
        //然后修改当前坐标的值
        matrix[i][j] = '.';
        //走递归,沿着当前坐标的上下左右4个方向查找
        boolean res = dfs(matrix, word, i + 1, j, index + 1)
                || dfs(matrix, word, i - 1, j, index + 1)
                || dfs(matrix, word, i, j + 1, index + 1)
                || dfs(matrix, word, i, j - 1, index + 1);
        //递归之后再把当前的坐标复原
        matrix[i][j] = tmp;
        return res;
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述

    JZ13 机器人的运动范围

    题目描述

    在这里插入图片描述
    在这里插入图片描述

    思路详解

    本题是一个机器人从左上角开始,他可以沿着上下左右四个方向走,并且走到的每个格子坐标的数字和不大于k,问可以走多少个格子。那么就想到本题就有两种解法,DFS 和 BFS,下面都列出来大家看下效率和具体实现方法。

    DFS(深度优先搜索)

    根据题目得出,机器人不能往回走,并且每个格子还有一个进入的方向,那么机器人可以走的就只有3个方向。但是我们用的是DFS(深度优先搜索),就像不撞南墙不回头的牛一样。实际上只有向右,向下,两个方向。
    我们试想一下,他会一直沿着一个方向走到不能走,然后回溯。那么这个时候回溯的时候我们在进行向下,向右,就可以达到所有的地方。
    详解见代码哦!!!

    BFS(广度优先搜索)

    当然也可以用BFS(广度优先搜索),相比于DFS,BFS就比较灵活咯。
    BFS不是一条道走下去,他会把离他最近的都访问一遍,访问完之后才开始访问第二近的……,直到访问完全部的。
    BFS使用最好的一种数据结构就是使用队列,因为队列是先进先出,离他最近的访问完之后加入到队列中,最先入队的也是最先出队的。
    具体代码与DFS相差不多,详见代码注释哦!!!

    代码与结果

    DFS(深度优先搜索)

    public int movingCount(int threshold, int rows, int cols) {
        //临时变量visited记录格子是否被访问过
        boolean[][] visited = new boolean[rows][cols];
        return dfs(0, 0, rows, cols, threshold, visited);
    }
     
    public int dfs(int i, int j, int rows, int cols, int threshold, boolean[][] visited) {
        //i >= rows || j >= cols是边界条件的判断,threshold < sum(i, j)判断当前格子坐标是否
        // 满足条件,visited[i][j]判断这个格子是否被访问过
        if (i >= rows || j >= cols || threshold < sum(i, j) || visited[i][j])
            return 0;
        //标注这个格子被访问过
        visited[i][j] = true;
        //沿着当前格子的右边和下边继续访问
        return 1 + dfs(i + 1, j, rows, cols, threshold, visited) +
                dfs(i, j + 1, rows, cols, threshold, visited);
    }
     
    //计算两个坐标数字的和
    private int sum(int i, int j) {
        int sum = 0;
        //计算坐标i所有数字的和
        while (i != 0) {
            sum += i % 10;
            i /= 10;
        }
        //计算坐标j所有数字的和
        while (j != 0) {
            sum += j % 10;
            j /= 10;
        }
        return sum;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在这里插入图片描述

    BFS(广度优先搜索)

    import java.util.LinkedList;
    import java.util.Queue;
     
    public class Solution {
        public int movingCount(int threshold, int rows, int cols) {
            //临时变量visited记录格子是否被访问过
            boolean[][] visited = new boolean[rows][cols];
            int res = 0;
            //创建一个队列,保存的是访问到的格子坐标,是个二维数组
            Queue<int[]> queue = new LinkedList<>();
            //从左上角坐标[0,0]点开始访问,add方法表示把坐标
            // 点加入到队列的队尾
            queue.add(new int[]{0, 0});
            while (queue.size() > 0) {
                //这里的poll()函数表示的是移除队列头部元素,因为队列
                // 是先进先出,从尾部添加,从头部移除
                int[] x = queue.poll();
                int i = x[0], j = x[1];
                //i >= rows || j >= cols是边界条件的判断,threshold < sum(i, j)判断当前格子坐标是否
                // 满足条件,visited[i][j]判断这个格子是否被访问过
                if (i >= rows || j >= cols || threshold < sum(i, j) || visited[i][j])
                    continue;
                //标注这个格子被访问过
                visited[i][j] = true;
                res++;
                //把当前格子右边格子的坐标加入到队列中
                queue.add(new int[]{i + 1, j});
                //把当前格子下边格子的坐标加入到队列中
                queue.add(new int[]{i, j + 1});
            }
            return res;
        }
     
        //计算两个坐标数字的和
        private int sum(int i, int j) {
            int sum = 0;
            //计算坐标i所有数字的和
            while (i != 0) {
                sum += i % 10;
                i /= 10;
            }
            //计算坐标j所有数字的和
            while (j != 0) {
                sum += j % 10;
                j /= 10;
            }
            return sum;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    在这里插入图片描述


    ✨总结

    本来今天要刷三题的,但是今天的DFS 和 BFS比较重要,就写的详细一点,也下去多练几题。
    本题也是面试官最喜欢考的题型,代码不多却体现了两种不同的思路。
    一起来多练习几遍吧,等你哦!!!

    原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

    点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

    收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

    评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

  • 相关阅读:
    链接文件学习(七):英飞凌MCU Tasking编译器LSL链接文件解析 及代码变量定位方法
    【论文阅读笔记】 Curated Pacific Northwest AI-ready Seismic Dataset
    XUnit数据共享与并行测试
    【tg】4:NetworkManager :p2p、ice、消息收发
    Android 11 热点(softap)流程分析(二) WifiManager--AIDL
    Laravel 6 - 第十七章 配置数据库
    Cocos Creator TypeScript 套牛游戏
    20221108:onnx2caffe错误处理
    Docker Compose 安装 MinIO 并设置用户名和密码
    LoRa技术实现智能城市的转型
  • 原文地址:https://blog.csdn.net/muzi_longren/article/details/126053327