【算法】Java-二叉树的右视图(BFS、DFS两种解法)

题目要求:

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

示例 2:

输入: [1,null,3]
输出: [1,3]

示例 3:

输入: []
输出: []

提示:

二叉树的节点个数的范围是[0,100]
-100<= Node.val <= 100


题目分析:

右视图,不仅仅是返回右子树上的节点,如果是一颗这样的树,我们要返回:1  3 5。

如果只返回右子树的节点,只返回1 3,就不符合右视图了。

返回每个层次最后一个节点,所以我用的第一个方法是:BFS-广度优先遍历。

方法一:广度优先遍历

思路:遍历每一层,将下一层的节点存到队列;如果是最后一个节点,add到返回集合;

图片来自LeetCode官方答案
public class RightViewTree {public List<Integer> rightSideView(TreeNode root) {List<Integer> res = new ArrayList<>();if (root == null) {return res;}ArrayDeque queue = new ArrayDeque(); queue.offer(root);while (queue.size() > 0) {int count = queue.size(); // ①记录当前层有多少个节点for (int i = 0; i < count; i++) {TreeNode node = (TreeNode) queue.poll();if (node.getLeftNode() != null) {queue.offer(node.getLeftNode());}if (node.getRightNode() != null) {queue.offer(node.getRightNode());}// 遍历到最后一个 add 到resif (i == count - 1) {res.add(node.val);}}}return res;}
}

另外:这是最终版,前面几版,除了把问题理解成了输出右子树的节点,还这样写过:

public List<Integer> rightSideView(TreeNode root) {List<Integer> res = new ArrayList<>();if(root == null){return res;}ArrayDeque queue = new ArrayDeque();queue.offer(root);int count = 1; // ①记录每层的节点个数while (queue.size()> 0){int add = 0;// 遍历队列 拿最后一个for(int i = 0; i < count ; i ++){TreeNode node =(TreeNode) queue.poll();if(node.getLeftNode() != null){queue.offer(node.getLeftNode());add ++;}if(node.getRightNode() != null){queue.offer(node.getRightNode());add ++;}// 遍历到最后一个 add 到resif(i == count -1){res.add(node.val);}}count = add;}return res;}

时间复杂度:O(N);

空间复杂度:O(N);

①与最终版的区别在于,如何记录每层的节点数,这里用了一个临时变量count;

学习了其他博主的写法之后,意识到每次for循环结束后,add到queue中的节点,就是下一层所有节点了,不用单独记,直接取size可以。

(后来我想当时还是没把queue中存的内容想清楚,才又count了一下,所以在这里标识一下)

方法二:深度优先遍历

思路:按照根->右->左 遍历二叉树,保证每层都是最先访问最右边的节点。

图片来自LeetCode官方答案

      这个方法最开始我没想出来,后来看了别人的解题思路,理解到这种方法的关键在于:遍历每个节点时,如何知道这个深度是否已经记录过最右侧的节点了?大家看答案之前可以先想一想。

答:使用递归,将深度作为入参记录到栈帧。

将节点add到返回集合中;通过对比深度和集合中节点的数量,就知道该层是否已经记录过。

public class RightViewTree {private static List<Integer> res = new ArrayList<>();/*** 深度优先遍历* @param root* @return*/private List<Integer> rightSideView(TreeNode root) {dfs(root, 0); // 从根节点开始访问,depth=0return res;}// 在使用递归进行深度优先遍历时,每个栈帧保存当时的depth。private void dfs(TreeNode root, int depth) {if (root == null) {return;}// 先访问 当前节点,再递归地访问右子树、左子树。// 每一层的depth一定,当depth>=res.size()时,说明该层还未记录,将节点add到返回集合中;在本题中,不会出现大于的情况,所以只需判断等于。// 又因为我们遍历的顺序是根-右-左,所以root一定是当前深度最右边的节点。if (depth == res.size()) {  res.add(root.val);}depth++; // 准备记录下一层dfs(root.getRightNode(), depth);dfs(root.getLeftNode(), depth);}}

时间复杂度:O(N);

空间复杂度:O(N);

    对于深度优先遍历或递归不了解的朋友,可能对depth的变化不太理解。可以结合栈帧中记录,多debug几遍。

    方法二可以帮助我们更好的理解递归中,递和归的过程,以及过程中变量的变化。

写在最后:

      这道题的解法有很多,分享这两种解法的原因是在做这道题时,我感受到了自己的一点点质变。方法一,对队列的熟练应用。方法二,深度理解了递归的过程,后面还要继续应用,继续体会。

      学习算法增加了我看问题的视角,经常感叹“原来可以这样”,“居然还能这样”,“这人想的真好”之类。但我们知道“知道”和“做到”之间,有一条“鸿沟”,用新的“知道”的方法解出题的感觉真是太棒了,我做到了!当然,过程非常不容易,经常有些题目都看不懂,或者别人的思路理解不了。这时候,我们要想想,这道题难度是不是太大了,如果太大,要降低难度;否则,多debug,或者把步骤一步步写在纸上,是个不错的方法;或者多看看别人的解题思路。

     开年的第一篇博客,是关于对算法的思考,太不可思议了!小王师傅做到了!希望能帮到一些朋友,有更多的朋友做到!

参考:

LeetCode官方:. - 力扣(LeetCode)

LeetCode Sweetiee博主的分享:. - 力扣(LeetCode)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

e2studio开发三轴加速度计LIS2DW12(3)----检测活动和静止状态

e2studio开发三轴加速度计LIS2DW12.3--检测活动和静止状态 概述视频教学样品申请源码下载新建工程工程模板保存工程路径芯片配置工程模板选择时钟设置UART配置UART属性配置设置e2studio堆栈e2studio的重定向printf设置R_SCI_UART_Open()函数原型回调函数user_uart_callback ()…

Jetpack Compose -> 声明式UI Modifier

前言 本章主要介绍下 Compose 的声明式 UI 以及初级写法&#xff1b; 什么是声明式UI 传统UI 传统 UI 方式来声明UI <androidx.appcompat.widget.LinearLayoutCompat android:layout_width"match_parent" android:layout_height"match_parent&quo…

test Property-based Testing-04-junit-quickcheck

拓展阅读 开源 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息) 开源 Junit performance rely on junit5 and jdk8.(java 性能测试框架。性能测试。压测。测试报告生成。) junit-quickcheck&#xff1a;基于 JUnit 风格的属性驱动测试库 junit-qu…

送水小程序开发:如何选择最适合的技术平台

选择最适合的技术平台对于开发送水小程序至关重要。在这篇文章中&#xff0c;我将为您介绍如何选择最适合的技术平台来开发送水小程序&#xff0c;以及各种技术平台的优缺点。无论您是刚刚起步的创业公司还是成熟的送水服务提供商&#xff0c;本文都将为您提供有关送水小程序开…

深信服超融合HCI版本升级,6.0.0R5升级至6.8.0R2

超融合升级&#xff0c;需要满足以下条件及前期准备&#xff1a; 确认HCI的升级序列号有效升级时长大概在一个半小时&#xff0c;安全起见&#xff0c;需预留至少三至四小时窗口期升级前&#xff0c;需要将所有虚拟机关机&#xff0c;涉及到业务无法访问&#xff0c;需提前通知…

网络-DHCP中继(思科)

思科 前提&#xff1a;将R1 R3配置16板卡 将R1更改标识符为三层交换机 将R3更改标识符为交换机 拓扑图&#xff1a; R2进行配置 配置IP地址 为12.0.0.2 配置默认路由到R1的f1/4接口 配置dhcp地址池 配置vlan10的地址池 配置vlan20的地址池 三层交换机R1进行配置 将f1/4接口…

高光谱分类论文解读分享之基于形态卷积神经网络的高光谱影像分类

IEEE TGRS 2021&#xff1a;基于形态卷积神经网络的高光谱影像分类 题目 Morphological Convolutional Neural Networks for Hyperspectral Image Classification 作者 Swalpa Kumar Roy; Ranjan Mondal; Mercedes E. Paoletti; Juan M. Haut; Antonio Plaza 关键词 Clas…

关于git与git-lfs对文件压缩存储方面的研究

先说结论&#xff0c;git使用了Delta增量压缩算法&#xff0c;git-lfs实测没有进行任何压缩&#xff0c;这个结论让我很震惊。 测试过程如下&#xff1a; 测试git仓库自身的压缩 准备一个包含许多杂项文件的文件夹&#xff0c;大概几百M&#xff0c;要保证有一个txt文本文件…

Qt框架学习 --- CTK编译(Qt5.15.2+vs2019+cmake)

系列文章目录 第二章 CTK的测试demo https://blog.csdn.net/yonug1107716573/article/details/135527289 文章目录 系列文章目录前言一、准备工作二、编译步骤1.修改文件2.编译CTK2.1 准备2.2 cmake界面配置2.3 配置编译器2.4 编译的配置设置2.5 选择需要编译的模块2.6 生成2.…

Uibot (RPA设计软件)股票板块行情抓取————课前材料四

微信群发助手机器人的小项目友友们可以参考小北的课前材料二博客~ (本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; 紧接着小北的前两篇博客&#xff0c;友友们我们即将开展新课的学习~RPA 培训前期准备指南——安装Uibot(RPA设计软件&#x…

Java 并发性和多线程3

七、线程安全及不可变性 当多个线程同时访问同一个资源&#xff0c;并且其中的一个或者多个线程对这个资源进行了写操作&#xff0c;才会产生竞态条件。多个线程同时读同一个资源不会产生竞态条件。 我们可以通过创建不可变的共享对象来保证对象在线程间共享时不会被修改&…

AI绘画风格化实战

在社交软件和短视频平台上&#xff0c;我们时常能看到各种特色鲜明的视觉效果&#xff0c;比如卡通化的图片和中国风的视频剪辑。这些有趣的风格化效果其实都是图像风格化技术的应用成果。 风格化效果举例 MidLibrary 这个网站提供了不同的图像风格&#xff0c;每一种都带有鲜…

Neo4j知识图谱(2)创建与删除

Neo4j - CQL简介_w3cschoolhttps://www.w3cschool.cn/neo4j/neo4j_cql_introduction.html一、创建节点 create(n:Person{name:何仙鸟,age:21}) create就是创建&#xff0c;无论是点还是边都是用create来创建 n相当于一个别名&#xff0c;比如创建一个Person&#xff0c;而Pe…

嵌入式软件面试之程序在存储器中的分布

Hi, 大家好&#xff0c;今天阿目分享的是一个嵌入式软件面试的常见问题&#xff0c;内存分布或者说程序在内存中的布局&#xff0c;我们写的程序是按照怎么的准则放在内存中的&#xff1f; 一般有操作系统的嵌入式设备&#xff0c;都会有一个Bootloader, 它负责在上电后初始化…

漏洞修复整理

一、Geoserver Apache HTTP/2拒绝服务漏洞&#xff08;CVE-2023-44487&#xff09;、Eclipse Jetty 资源管理错误漏洞(CVE-2023-26048)、Eclipse Jetty 信息泄露漏洞(CVE-2023-26049) 受影响版本&#xff1a;9.4.53以下版本 处理方式&#xff1a;原地升级 &#xff08; jdk版本…

学习redis有效期和数据类型

1、安装redis和连接redis 参考&#xff1a;ubuntu安装单个redis服务_ubuntu redis单机版安装-CSDN博客 连接redis&#xff1a;redis-cli.exe -h localhost -p 6379 -a 123456 2、Redis数据类型 以下操作我们在图形化界面演示。 2.1、五种常用数据类型介绍 Redis存储的是key…

jenkins-cl参数化构建

pipeline片段&#xff08;对应jenkins-cli -p参数的BRANCHdevelop&#xff09; parameters {string(name: BRANCH, defaultValue: master, description: Enter the branch name)}stages {stage(Get Code) {steps {script {def branch params.BRANCHcheckout scmGit(branches: …

算法通关村第十五关—继续研究超大规模数据场景的问题(黄金)

继续研究超大规模数据场景的问题 一、对20GB文件进行排序 题目要求&#xff1a;假设你有一个20GB的文件&#xff0c;每行一个字符串&#xff0c;请说明如何对这个文件进行排序&#xff1f;  分析&#xff1a;这里给出大小是20GB,其实面试官就在暗示你不要将所有的文件都装入到…

世邦通信 SPON IP网络对讲广播系统addscenedata.php任意文件上传漏洞

产品介绍 世邦通信SPON IP网络对讲广播系统采用领先的IPAudio™技术,将音频信号以数据包形式在局域网和广域网上进行传送,是一套纯数字传输系统。 漏洞描述 spon IP网络对讲广播系统存在任意文件上传漏洞&#xff0c;攻击者可以通过构造特殊请求包上传恶意后门文件&#xff…

Sentinel微服务保护

文章目录 Sentinel微服务保护1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.解决方案1.1.3.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel 1.4.微服务整合Sentinel 2.流量控制2.1.簇点链路2.1.快速入门2.2.流控模式2.2.1.…