java算法day14

news/2024/9/11 3:43:53/ 标签: 算法, java, leetcode

javaday14_0">java算法day14

  • 222 完全二叉树的节点个数。
  • 110 平衡二叉树
  • 257 二叉树的所有路径

222 完成二叉树的节点个数

解法1,层序遍历,迭代解法。
就是层序遍历的模板题。

java">/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public int countNodes(TreeNode root) {Deque<TreeNode> que = new ArrayDeque<>();if(root==null){return 0;}que.offerLast(root);int count = 0;while(!que.isEmpty()){int size = que.size();count +=size;while(size>0){TreeNode temp = que.pollFirst();if(temp.left!=null){que.offerLast(temp.left);}if(temp.right!=null){que.offerLast(temp.right);}size--;}}return count;}
}

解法二:递归解法。

首先还是不要扣细节,从大体上观察,然后才是拆分子问题求解。

大体上就是计算root的左右子树的节点个数总和相加,然后算上root就是+1。
如果是为null了,那说明下面没有了,直接return 0。所以递归出口也找到了。

java">class Solution {public int countNodes(TreeNode root) {if(root==null){return 0;}//返回左右子树的节点总和,然后加上本层的节点。return 1+countNodes(root.left)+countNodes(root.right);}
}

110 平衡二叉树

解法1:
还是递归思想。
粗略的来想。
递归的过程中,每一层需要做的事就是计算左右子树的最大高度的绝对值相减是否大于。然后递归检查左右子树。根据这个思想可以得到。

这题我写的时候没注意到一个问题,一定要紧扣题目问什么,这题我就忘写了与题目相关的进入下一层的逻辑。

java">class Solution {public boolean isBalanced(TreeNode root) {//能走到这说明到底了,那就是这个过程都是满足条件,所以为trueif(root==null){return true;}//每层要干的事if(Math.abs(maxDepth(root.left)-maxDepth(root.right))>1){return false;}//进入下一层。return isBalanced(root.left) && isBalanced(root.right);}//写一个函数来递归计算左右子树的最大高度int maxDepth(TreeNode root){if(root==null){return 0;}int leftMax = maxDepth(root.left);int rightMax = maxDepth(root.right);return 1+Math.max(leftMax,rightMax);}
}

这个解法有弊端,我这种解法属于自顶向下的,所以有很多的冗余计算,冗余的地方在于,我每次进入下一层,我就要调用一次计算左右子树最大高度,算一次最大高度,那就要往下递归。

所以这就是优化的地方。因此有了解法二


解法二:自底向下解法。

https://leetcode.cn/problems/balanced-binary-tree/solutions/746538/shu-ju-jie-gou-he-suan-fa-ping-heng-er-c-ckkm/
这篇题解是我看过最直观的图解。

思路:
1.这也是做本题得到的一个新思考,怎样才能做到自顶向上? 回答是利用后序遍历的思想。在后序遍历中,我们先处理左子树,然后右子树,最后才是处理当前节点。这样就做到了得到左右子树的全部信息后才来处理当前节点。而且还是在回溯的过程中进行。
总结:后序遍历提供了自底向上的信息流

2.代码整体思路:
使用一个辅助函数height来同时计算树的高度和检查平衡性。如果树是平衡的,height返回树的实际高度。如果不平衡,返回-1。
主函数要干的就是返回这个辅助函数的返回结果,如果辅助函数返回-1,那么,在底部就有一个位置不满足平衡二叉树的条件。平衡二叉树的判定是,每个节点都要递归的满足平衡二叉树的定义。由于是自底向上返回结果,所以,这个-1的值是可以带上来的,只要做条件判断即可。

3.辅助函数的具体细节
就按上面所说的想法实现,但是用的是后序遍历。由于平衡二叉树的判断本质还是左右子树高度查,因此在每一层还是要计算左右子树的高度查。但他不一样的点就在于,结果直接是从底层开始计算,所以只要底层返回了下面的高度,就可以避免重复的计算。

接下来直接看代码。

java">class Solution {public boolean isBalanced(TreeNode root) {//就是返回辅助函数的结果return height(root)>=0;}//传根节点进来public int height(TreeNode root){//递归出口,到底了,返回值就是0。没有高度if(root==null){return 0;}//后序遍历的思想,先往底部走int leftHeight = height(root.left);int rightHeight = height(root.right);//这里就是到了底层之后,归 的逻辑//之前说了,一旦有一个子树不满足平衡二叉树的定义,那么整体就不满足,所以这个结果要带上去。每一层都做这样的判断,那就能够带到顶部。//返回-1的情况有三种,左子树上有不满足的,或者右子树上有不满足的,或者到当前层才不满足的。if(leftHeight==-1 || rightHeight==-1 || Math.abs(leftHeight-rightHeight)>1){return -1;}else{//能走到这说明左右子树都满足了二叉平衡树,那么加上本层的高度,往上返回。return Math.max(leftHeight,rightHeight)+1;}}
}

从底部,得出底部的信息,归的时候带上底部的信息,可以避免重复计算。从而实现优化。


二叉树路径问题

主要分为两大类。

1.自顶向下:

就是从某一个节点(不一定是根节点),从上到下寻找路径,到某一个节点(不一定是叶节点)结束。


自顶向下解题模板

首先想想自顶向下这个过程,可以清楚的类比为前序遍历的过程。因此理解下面模板的过程中,就当为前序遍历。


不回溯版本
java">class Solution {//用于收集所有路径的结果集List<List<Integer>> res = new ArrayList<>();//主函数,用来启动dfs,最后返回所有路径的结果集public List<List<Integer>> findPaths(TreeNode root) {dfs(root, new ArrayList<>());return res;}private void dfs(TreeNode root, List<Integer> path) {//递归出口。一旦走到了这里,说明走到了叶子节点下面的空节点。所以下面就不用担心path.add收集到空的问题。if (root == null) return;//所以每进到下一层,就先收集节点。     path.add(root.val);//然后判断是否是叶子节点,是的话就把路径加入结果集res。然后return,这条路就已经走完了。if (root.left == null && root.right == null) {//这里也是一个细节,这里是复制一份path,因为如果直接用那份path,在之后的状态会影响到里面的元素,所以这里是复制一份路径,加入结果集。res.add(new ArrayList<>(path));return;}//这里也是递归左右子树,因为你要分开了,两条路的后面的路径肯定是不相同的,所以后面的路径要分别新弄一个副本记录。如果用同一个path,那么就会导致path里面的元素会互相影响。dfs(root.left, new ArrayList<>(path));dfs(root.right, new ArrayList<>(path));}
}
回溯版本
java">class Solution {
//结果集List<List<Integer>> res = new ArrayList<>();//主函数public List<List<Integer>> findPaths(TreeNode root) {dfs(root, new ArrayList<>());return res;}private void dfs(TreeNode root, List<Integer> path) {//递归出口if (root == null) return;path.add(root.val);//检查是否为叶子节点,这里不同于非回溯的点就在于,你在判断为是叶子节点后,也不能直接停下来,而是要进行回溯。即处理完这层的结果集之后,还要把刚刚加进来的元素给删了。这才完成了该叶子节点的任务。//本质还是前序遍历。if (root.left == null && root.right == null) {res.add(new ArrayList<>(path));} else {//递归遍历左右子树。现在可以看到,用的一直都是同一个path了。dfs(root.left, path);dfs(root.right, path);}//回溯//这里回溯的思考很重要//回溯并不是只删除刚加入的叶子节点,而是不管是任意节点,在完成当前节点的探索之后,需要将当前节点从路径中移除。所以上面的dfs下一层之后,回来的时候还是要走remove回溯。//确保我们回到父节点时,路径恢复到进入当前节点的状态。path.remove(path.size() - 1);  // 回溯}
}

2.非自顶向下:

就是从任意节点到任意节点的路径,不需要自顶向下。

257 二叉树的所有路径

类别为:自顶向下

所以用回溯的模板做

java">class Solution {public List<String> binaryTreePaths(TreeNode root) {List<String> result = new ArrayList<>();if (root == null) return result;dfs(root, new StringBuilder(), result);return result;}private void dfs(TreeNode node, StringBuilder path, List<String> result) {if (node == null) return;int len = path.length();if (len > 0) path.append("->");path.append(node.val);if (node.left == null && node.right == null) {result.add(path.toString());} else {dfs(node.left, path, result);dfs(node.right, path, result);}path.setLength(len);  // 回溯}
}

不回溯的模板:

java">/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public List<String> binaryTreePaths(TreeNode root) {List<String> result = new ArrayList<>();if (root == null) return result;dfs(root, "", result);return result;}private void dfs(TreeNode node, String path, List<String> result) {if (node == null) return;path += node.val;if (node.left == null && node.right == null) {result.add(path);return;}path += "->";dfs(node.left, path, result);dfs(node.right, path, result);}
}

http://www.ppmy.cn/news/1475397.html

相关文章

图论基础概念(详细讲解)

今天&#xff0c;我们讲解一下图论的概念&#xff0c;首先我们知道图是一个什么东西。 图你可以理解成一个网络系统&#xff0c;两个节点之间可能会有边&#xff0c;边链接两个节点&#xff0c;可能是有向&#xff08;就比如说a只能往b,或者b只能往c)&#xff0c;可能是无向&a…

windows信息收集和提权

目录 手动收集 工具收集 windows本地内核提权 本地提权 根据windows去找需要的exp进行利用 提权后结合mimikatz使用 msf提权 简单提权 生成后门 上线 BypassUAC绕过UAC提权 msf带的bypassuac模块可以尝试提权 Bypassuac提权命令操作 提权成功 ​local_exploi…

Xcode数据分析全解:洞察应用性能的密钥

标题&#xff1a;Xcode数据分析全解&#xff1a;洞察应用性能的密钥 在应用开发和优化的过程中&#xff0c;数据分析是提升用户体验和应用性能的关键步骤。Xcode作为苹果官方的集成开发环境&#xff0c;提供了多种工具和集成方案来支持应用的数据分析。本文将详细介绍如何在Xc…

WordPress主题底部纯文本文章列表

如果是RiPro主题&#xff0c;请在后台顶部设置添加自定义CSS。其他主题在对应的CSS样式添加。 CSS代码&#xff1a; /*底部纯文本文章列表*/ .sjblog-list {height: 90px;background: #333;border-radius: 4px 4px 0 0;padding: 24px;margin: -20px -20px 22px -20px;positio…

守护服务之门:Eureka中分布式认证与授权的实现策略

守护服务之门&#xff1a;Eureka中分布式认证与授权的实现策略 引言 在微服务架构中&#xff0c;服务间的通信安全至关重要。Eureka作为Netflix开源的服务发现框架&#xff0c;虽然本身提供了服务注册与发现的功能&#xff0c;但并不直接提供认证与授权机制。为了实现服务的分…

Java面试八股之Redis单线程为什么性能高

Redis单线程为什么性能高 1.内存数据库特性 要点&#xff1a;Redis是一个内存数据库&#xff0c;其数据主要存储在内存中&#xff0c;而非磁盘。内存访问的速度远超磁盘&#xff0c;通常可达纳秒级别&#xff0c;这使得Redis在处理数据时几乎不受I/O瓶颈的影响。由于数据操作…

LeetCode(2)-反转链表、删除链表中等于val的节点、返回链表中的中间节点

一、反转链表 . - 力扣&#xff08;LeetCode&#xff09; 解法1&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ typedef struct ListNode ListNode; struct ListNode* reverseList(struct ListN…

“论基于构件的软件开发方法及其应用”精选范文,软考高级论文,系统架构设计师论文

论文真题 基于构作的软件开发 (Component-Based Software Development&#xff0c;CBSD) 是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。基于构件的软件系统中的构件可以是COTS &#xff08;Commercial-Off-the-Shelf&#xff09;构件&#x…

C#winfrom窗体开发图书管理系统

一、图书管理系统设计背景 图书馆管理系统是一个关键的信息技术应用&#xff0c;旨在提升图书馆的运营效率和用户的借阅体验。该系统通过数字化手段&#xff0c;实现了图书资源的高效管理和用户服务的便捷化。随着数字化时代的到来&#xff0c;传统的图书馆管理方式已经不能满…

Java实现将图片转换成PDF

1.引入依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.24</version> </dependency>2.工具方法 package com.prescription.transfer.system.utils;import org.apache.p…

flutter 列表下拉框加搜索

1.使用控件搜索加下拉框dropdown_search: ^0.4.9和获取中文拼音lpinyin: ^1.1.1 2.加入中文查询和首字查询 在当中找到相应的packages&#xff0c;再在SelectDialog.dart当中加入引入拼音搜索 import package:lpinyin/lpinyin.dart; 更改匹配方法manageItemsByFilter使其可…

R包: phyloseq扩增子统计分析利器

介绍 phyloseq包对多类型数据的综合软件&#xff0c;并其对这些数据提供统计分析和可视化方法。 微生物数据分析的主要挑战之一是如何整合不同类型的数据&#xff0c;从而对其进行生态学、遗传学、系统发育学、多元统计、可视化和检验等分析。同时&#xff0c;由于同行之间需要…

期货量化交易客户端开源教学第九节——新用户注册

一、新用户注册界面设计&#xff1a; 注册时采用手机号注册&#xff0c;客户端发送新号注册申请由后台做审核&#xff0c;后台审核通过后向注册的手机号发送注册成功的消息。注册过的手机号不能再二次注册。 界面验证代码 private{ Private declarations }FVerf: AnsiString; …

【QT】布局管理器

布局管理器 布局管理器1. 垂直布局2. 水平布局3. 网格布局4. 表单布局5. Spacer 布局管理器 之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的&#xff1b;也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move ⽅式摆放过去。 …

java 前端上传文件后端解析并转发到第三方存储,Hutool 工具

单个文件上传 PostMapping("/upload")public MyResponse<?> upload(MultipartFile file) {if (multipartFiles null || multipartFiles.length 0) {throw new MessageException("未选择文件");}InputStreamResource inputStreamResource new Inp…

实用教程:用 Go 的 net/textproto 包优化文本协议处理

实用教程&#xff1a;用 Go 的 net/textproto 包优化文本协议处理 介绍准备工作环境设置Go 基础回顾 基础使用创建连接发送请求接收响应 高级特性处理 MIME 头多行响应的管理错误处理与调试 实战案例实现一个简单的邮件客户端实现一个基于 net/textproto 的命令行工具 最佳实践…

从零开始开发视频美颜SDK:实现直播美颜效果

因此&#xff0c;开发一款从零开始的视频美颜SDK&#xff0c;不仅可以节省成本&#xff0c;还能根据具体需求进行个性化调整。本文将介绍从零开始开发视频美颜SDK的关键步骤和实现思路。 一、需求分析与技术选型 在开发一款视频美颜SDK之前&#xff0c;首先需要进行详细的需求…

WPF界面设计-更改按钮样式 自定义字体图标

一、下载图标文件 iconfont-阿里巴巴矢量图标库 二、xaml界面代码编辑 文件结构 &#xe653; 对应的图标代码 Fonts/#iconfont 对应文件位置 <Window.Resources><ControlTemplate TargetType"Button" x:Key"CloseButtonTemplate"…

数据结构与算法基础-学习-37-平衡二叉树(Avl树)之删除节点

目录 一、知识点回顾 1、二叉搜索树&#xff08;BST&#xff09; 2、平衡二叉树&#xff08;Avl树&#xff09;之查找 二、环境信息 三、实现思路 1、示例图 2、查询 3、删除 &#xff08;1&#xff09;叶子节点&#xff08;无子树节点&#xff09; &#xff08;2&am…

如何为IP申请SSL证书

目录 以下是如何轻松为IP地址申请SSL证书的详细步骤&#xff1a; 申请IP证书的基本条件&#xff1a; 申请IP SSL证书的方式&#xff1a; 确保网络通信安全的核心要素之一&#xff0c;是有效利用SSL证书来加密数据传输&#xff0c;特别是对于那些直接通过IP地址访问的资源。I…