蓝桥杯 Java B 组之岛屿数量、二叉树路径和(区分DFS与回溯)

Day 3:岛屿数量、二叉树路径和(区分DFS与回溯)


📖 一、深度优先搜索(DFS)简介

深度优先搜索(Depth-First Search,DFS)是一种用于遍历或搜索树或图的算法。它会沿着树的分支向下深入,直到节点无法继续深入为止(即叶子节点),然后返回并访问未遍历的分支。

DFS的典型应用场景包括:

  • 图的遍历:搜索图中的连通区域。
  • 树的遍历:包括前序、中序、后序遍历。
  • 岛屿数量问题:在二维网格中查找连通的区域。
  • 路径问题:寻找路径和进行条件限制。

DFS通常使用递归实现,也可以使用栈来模拟递归过程。

DFS与回溯的区别:

  • DFS:DFS侧重于遍历或搜索所有可能的路径。它没有特定的“回溯”条件,而是遍历完一个分支后直接回退,直到找到其他未访问的节点。
  • 回溯:回溯通常用于寻找“所有解”,即我们在遍历某一路径时,如果发现该路径无法继续时会“回退”并尝试其他路径。回溯是一种基于试探的搜索。

简而言之:回溯是一种DFS的应用,当我们通过DFS遍历所有路径时,如果某一路径不满足条件,我们需要回退并尝试其他路径。


📖 二、岛屿数量问题

问题描述: 给定一个由 '1'(陆地)和 '0'(水域)组成的二维网格,计算网格中岛屿的数量。岛屿是由一组相邻的 '1'(陆地)组成的,水平或垂直方向上相邻的陆地算作一个岛屿。

思路与分析

  1. 我们可以使用DFS来遍历所有陆地块,并在遍历的过程中标记已经访问过的陆地。
  2. 遍历二维数组中的每个点,如果是陆地 ('1'),就从这个点开始执行DFS,标记与其相连的所有陆地为已访问。
  3. 每次启动DFS时,我们会遇到一个新的岛屿,因此岛屿数量加1。

DFS的递归实现

  1. 对于每个陆地点('1'),启动DFS,将与它相连的所有陆地都标记为访问过(可以改为'0'或者使用一个visited数组)。
  2. 每次DFS的调用都从当前陆地开始,探索四个方向(上下左右),并继续递归。

代码实现(岛屿数量)

public class IslandCount {
    // 方向数组,用于上下左右遍历
    private static final int[] DIRS = {-1, 0, 1, 0, -1, 0};

    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        
        int rows = grid.length;
        int cols = grid[0].length;
        int islandCount = 0;
        
        // 遍历整个网格
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                // 找到一个陆地'1',则触发DFS进行标记
                if (grid[i][j] == '1') {
                    islandCount++;
                    // 从当前岛屿的陆地开始DFS
                    dfs(grid, i, j, rows, cols);
                }
            }
        }
        
        return islandCount;
    }

    // 深度优先搜索(DFS)
    private void dfs(char[][] grid, int i, int j, int rows, int cols) {
        // 如果越界或当前位置是水域('0'),返回
        if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] == '0') {
            return;
        }
        
        // 标记当前陆地为水域
        grid[i][j] = '0';
        
        // 递归检查四个方向(上下左右)
        for (int d = 0; d < 4; d++) {
            int newI = i + DIRS[d];
            int newJ = j + DIRS[d + 1];
            dfs(grid, newI, newJ, rows, cols);
        }
    }

    public static void main(String[] args) {
        IslandCount ic = new IslandCount();
        char[][] grid = {
            {'1', '1', '0', '0', '0'},
            {'1', '1', '0', '0', '0'},
            {'0', '0', '1', '1', '1'},
            {'0', '0', '1', '1', '0'}
        };
        System.out.println(ic.numIslands(grid)); // 输出 3
    }
}

代码讲解:

  1. DFS方法dfs(grid, i, j, rows, cols),从当前点(i, j)开始,遍历四个方向,递归地标记所有连通的陆地为水域('0'),避免重复计数。
  2. 主方法numIslands,遍历整个网格,每遇到一个'1',就触发DFS,增加岛屿计数。

时间复杂度

  • O(m * n),其中 m 是网格的行数,n 是网格的列数。每个格子最多访问一次。

📖 三、二叉树路径和问题

问题描述: 给定一个二叉树,求从根到叶子节点的所有路径和。返回所有路径和的总和。

思路与分析

  1. 使用DFS遍历二叉树的每个节点,并计算路径和。
  2. 每到一个叶子节点,就将当前路径和添加到结果列表中。
  3. 在DFS过程中,我们不断传递当前路径和,直到叶子节点。

DFS的递归实现

  1. 在每个节点,计算当前路径和(当前路径和 = 上一个路径和 + 当前节点值)。
  2. 递归地访问左右子树,直到叶子节点。
  3. 遇到叶子节点时,将路径和加入到结果集。

代码实现(二叉树路径和)

import java.util.*;

public class BinaryTreePathSum {
    // 二叉树节点定义
    static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;
        TreeNode(int x) { val = x; }
    }

    public List<String> binaryTreePaths(TreeNode root) {
        List<String> result = new ArrayList<>();
        if (root != null) {
            dfs(root, "", result);
        }
        return result;
    }

    // DFS方法
    private void dfs(TreeNode node, String path, List<String> result) {
        // 叶子节点,路径加上当前节点的值,添加到结果集
        if (node.left == null && node.right == null) {
            result.add(path + node.val);
            return;
        }

        // 递归访问左右子树
        if (node.left != null) {
            dfs(node.left, path + node.val + "->", result);
        }
        if (node.right != null) {
            dfs(node.right, path + node.val + "->", result);
        }
    }

    public static void main(String[] args) {
        // 构造一个简单的二叉树
        TreeNode root = new TreeNode(1);
        root.left = new TreeNode(2);
        root.right = new TreeNode(3);
        root.left.right = new TreeNode(5);

        BinaryTreePathSum solution = new BinaryTreePathSum();
        System.out.println(solution.binaryTreePaths(root)); // 输出 ["1->2->5", "1->3"]
    }
}

代码讲解:

  1. DFS方法dfs(node, path, result),从当前节点开始,构建路径。如果当前节点是叶子节点,保存路径。如果不是叶子节点,则递归访问左右子树。
  2. 路径拼接:路径通过字符串拼接来构建,格式为 root->left->right

时间复杂度

  • O(n),其中 n 是二叉树的节点数。每个节点都会被访问一次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973660.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【鸿蒙开发】第四十三章 Notification Kit(用户通知服务)

目录​​​​​​​ 1 简介 1.1 使用场景 1.2 能力范围 1.3 业务流程 1.4 通知样式 1.5 约束限制 1.6 与相关Kit的关系 2 请求通知授权 2.1 接口说明 2.2 开发步骤 3 管理通知角标 3.1 接口说明 3.2 开发步骤 4 管理通知渠道 4.1 通知渠道类型说明 4.2 接口说明…

SpringBoot:SSL证书部署+SpringBoot实现HTTPS安全访问

一、前言 SSL协议介于TCP/IP协议栈的第四层&#xff08;传输层&#xff09;和第七层&#xff08;应用层&#xff09;之间&#xff0c;为基于TCP的应用层协议&#xff08;如HTTP&#xff09;提供安全连接。它通过在客户端和服务器之间建立一个加密的通道&#xff0c;确保数据在传…

【数学】数论干货(疑似密码学基础)

文章目录 前言一. 整除、算术基本定理、同余、同余类、剩余系的基本定义1.整除2.算数基本定理3.同余4.同余类&#xff08;也叫剩余类&#xff09;5.剩余系 二. 费马小定理的内容及其证明1.费马小定理基本内容2.费马小定理的证明&#xff08;interesting 版&#xff09; 三. 欧拉…

[实现Rpc] 消息抽象层的具体实现

目录 具象层 _ 消息抽象的实现 信息的抽象类 实现 JsonMessage JsonRequest & JsonResponse 消息-不同消息分装实现 实现 Request RpcRequest TopicRequest ServiceRequest Response RpcResponse TopicResponse ServiceResponse 实现 生产工厂 本篇文章继 …

《A++ 敏捷开发》- 16 评审与结对编程

客户&#xff1a;我们的客户以银行为主&#xff0c;他们很注重质量&#xff0c;所以一直很注重评审。他们对需求评审、代码走查等也很赞同&#xff0c;也能找到缺陷&#xff0c;对提升质量有作用。但他们最困惑的是通过设计评审很难发现缺陷。 我&#xff1a;你听说过敏捷的结对…

PHP房屋出租出售高效预约系统小程序源码

&#x1f3e0; 房屋出租出售高效预约系统 —— 您的智能找房新选择 &#x1f4a1; 这是一款集智慧与匠心于一体的房屋出租出售预约系统&#xff0c;它巧妙地融合了ThinkPHP与Uniapp两大先进框架&#xff0c;精心打造而成。无论是小程序、H5网页&#xff0c;还是APP端&#xff…

给老系统做个安全检查——Burp SqlMap扫描注入漏洞

背景 在AI技术突飞猛进的今天&#xff0c;类似Cursor之类的工具已经能写出堪比大部分程序员水平的代码了。然而&#xff0c;在我们的代码世界里&#xff0c;仍然有不少"老骥伏枥"的系统在兢兢业业地发光发热。这些祖传系统的代码可能早已过时&#xff0c;架构可能岌…

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…

【DeepSeek】Mac m1电脑部署DeepSeek

一、电脑配置 个人电脑配置 二、安装ollama 简介&#xff1a;Ollama 是一个强大的开源框架&#xff0c;是一个为本地运行大型语言模型而设计的工具&#xff0c;它帮助用户快速在本地运行大模型&#xff0c;通过简单的安装指令&#xff0c;可以让用户执行一条命令就在本地运…

dockerfile 使用环境变量

ARG&#xff1a; Defining build-time variables ARG指令允许您定义在构建阶段可以访问但在构建映像之后不可用的变量。例如&#xff0c;我们将使用这个Dockerfile来构建一个映像&#xff0c;我们在构建过程中使用ARG指令指定的变量。 FROM ubuntu:latest ARG THEARG"fo…

基于WebGIS技术的校园地图导航系统架构与核心功能设计

本文专为IT技术人员、地理信息系统&#xff08;GIS&#xff09;开发者、智慧校园解决方案架构师及相关领域的专业人士撰写。本文提出了一套基于WebGIS技术的校园地图导航系统构建与优化方案&#xff0c;旨在为用户提供高效、智能、个性化的导航体验。如需获取校园地图导航系统技…

idea连接gitee(使用idea远程兼容gitee)

文章目录 先登录你的gitee拿到你的邮箱找到idea的设置选择密码方式登录填写你的邮箱和密码登录成功 先登录你的gitee拿到你的邮箱 具体位置在gitee–>设置–>邮箱管理 找到idea的设置 选择密码方式登录 填写你的邮箱和密码 登录成功

【从0做项目】Java音缘心动(3)———加密算法 MD5 BCrypt

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 零&#xff1a;项目结果展示 一&#xff1a;音乐播放器Web网页介绍 二&#xff1a;加密算法介绍 1&…

新数据结构(12)——代理

什么是代理 在进行操作时有时不希望用户直接接触到目标&#xff0c;这时需要使用代理让用户间接接触到目标 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制着对目标对象的引用 图解&#xff1a; 代理的目的 控制访问&#xff1a;通过代理对象的方式间接的访问目…

基于大语言模型的推荐系统(1)

推荐系统&#xff08;recommendation system&#xff09;非常重要。事实上&#xff0c;搜索引擎&#xff0c;电子商务&#xff0c;视频&#xff0c;音乐平台&#xff0c;社交网络等等&#xff0c;几乎所有互联网应用的核心就是向用户推荐内容&#xff0c;商品&#xff0c;电影&…

学习threejs,使用MeshBasicMaterial基本网格材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshBasicMaterial 二…

Selenium实战案例2:东方财富网股吧评论爬取

上一篇文章&#xff0c;我们使用Selenium完成了网页内文件的自动下载,本文我们将使用Selenium来爬取东方财富网股吧内笔记的评论数据。 网页内容分析 网页内容的分析是web自动化中的关键一步。通过分析网页结构&#xff0c;我们可以确定需要抓取的数据位置以及操作元素的方式。…

零基础学python--------第三节:Python的流程控制语法

Python&#xff0c;浮点数 11.345(单&#xff1a;4个字节&#xff0c; 双&#xff1a;8个字节) 。 十进制的数字25 ---> 11001 讲一个小数转化为二进制&#xff1a; 不断的乘以2 。取整数部分。 十进制的0.625 ----> 二进制&#xff1a; 0&#xff0c; 101 。 0.3 ---…

MKS SERVO42E57E 闭环步进电机_系列10 STM32_脉冲和串口例程

文章目录 第1部分 产品介绍第2部分 相关资料下载2.1 MKS E系列闭环步进驱动资料2.2 源代码下载2.3 上位机下载 第3部分 脉冲控制电机运行示例第4部分 读取参数示例4.1 读取电机实时位置4.2 读取电机实时转速4.3 读取电机输入脉冲数4.4 读取电机位置误差4.5 读取电机IO端口状态 …

小米路由器 AX3000T 降级后无法正常使用,解决办法

问题描述 买了个 AX3000T 路由器&#xff0c;想安装 OpenWRT 或者 安装 Clash 使用&#xff0c;看教程说是需要降级到 v1.0.47 版本。 结果刷机之后路由器无法打开了&#xff0c;一直黄灯亮&#xff0c;中间灭一下&#xff0c;又是黄灯长亮&#xff0c;没有 WIFI 没有连接。以…