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

简介: ✨今日二剑JZ12 矩阵中的路径JZ13 机器人的运动范围

✨今日二剑


JZ12 矩阵中的路径

JZ13 机器人的运动范围


文章目录

✨今日二剑

JZ12 矩阵中的路径

JZ13 机器人的运动范围

JZ12 矩阵中的路径

题目描述

思路详解

代码与结果

JZ13 机器人的运动范围

题目描述

思路详解

DFS(深度优先搜索)

BFS(广度优先搜索)

代码与结果

DFS(深度优先搜索)

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;
}
}


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;
}

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;
    }
}


✨总结


本来今天要刷三题的,但是今天的DFS 和 BFS比较重要,就写的详细一点,也下去多练几题。

本题也是面试官最喜欢考的题型,代码不多却体现了两种不同的思路。

一起来多练习几遍吧,等你哦!!!



相关文章
|
4月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
4月前
|
存储 缓存 监控
上网行为监控系统剖析:基于 Java LinkedHashMap 算法的时间序列追踪机制探究
数字化办公蓬勃发展的背景下,上网行为监控系统已成为企业维护信息安全、提升工作效能的关键手段。该系统需实时记录并深入分析员工的网络访问行为,如何高效存储和管理这些处于动态变化中的数据,便成为亟待解决的核心问题。Java 语言中的LinkedHashMap数据结构,凭借其独有的有序性特征以及可灵活配置的淘汰策略,为上网行为监控系统提供了一种兼顾性能与功能需求的数据管理方案。本文将对LinkedHashMap在上网行为监控系统中的应用原理、实现路径及其应用价值展开深入探究。
101 3
|
4月前
|
人工智能 算法 NoSQL
LRU算法的Java实现
LRU(Least Recently Used)算法用于淘汰最近最少使用的数据,常应用于内存管理策略中。在Redis中,通过`maxmemory-policy`配置实现不同淘汰策略,如`allkeys-lru`和`volatile-lru`等,采用采样方式近似LRU以优化性能。Java中可通过`LinkedHashMap`轻松实现LRUCache,利用其`accessOrder`特性和`removeEldestEntry`方法完成缓存淘汰逻辑,代码简洁高效。
182 0
|
3月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
332 58
|
2月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
|
2月前
|
存储 监控 算法
企业上网监控场景下布隆过滤器的 Java 算法构建及其性能优化研究
布隆过滤器是一种高效的数据结构,广泛应用于企业上网监控系统中,用于快速判断员工访问的网址是否为违规站点。相比传统哈希表,它具有更低的内存占用和更快的查询速度,支持实时拦截、动态更新和资源压缩,有效提升系统性能并降低成本。
58 0
|
2月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
131 0
|
2月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
284 83
|
3月前
|
存储 SQL 安全
Java 无锁方式实现高性能线程实战操作指南
本文深入探讨了现代高并发Java应用中单例模式的实现方式,分析了传统单例(如DCL)的局限性,并提出了多种无锁实现方案。包括基于ThreadLocal的延迟初始化、VarHandle原子操作、Record不可变对象、响应式编程(Reactor)以及CDI依赖注入等实现方式。每种方案均附有代码示例及适用场景,同时通过JMH性能测试对比各实现的优劣。最后,结合实际案例设计了一个高性能配置中心,展示了无锁单例在实际开发中的应用。总结中提出根据场景选择合适的实现方式,并遵循现代单例设计原则以优化性能和安全性。文中还提供了代码获取链接,便于读者实践与学习。
94 0

热门文章

最新文章