训练营第十八天(二叉树part05)

news2024/11/19 16:45:56

第十八天 二叉树part05

513.找树左下角的值

力扣题目链接(opens new window)

题目

给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:

513.找树左下角的值

示例 2:

在这里插入图片描述

解答

方法一(笨方法,使用层次遍历迭代)
class Solution {
    public int findBottomLeftValue(TreeNode root) {
		int result = 0;
		Queue<TreeNode> queue = new LinkedList<>();
		queue.offer(root);
		while (!queue.isEmpty()){
			int len = queue.size();
			result = queue.peek().val;//永远是最左边先入队
			while (len-- > 0){
				TreeNode temp = queue.poll();
				if (temp.left != null)
					queue.offer(temp.left);
				if (temp.right != null)
					queue.offer(temp.right);
			}
		}
		return result;
    }
}
方法二(递归)

所谓的回溯也就是深度不能变,在遍历左子树时,深度+了就要再-回来,不然再进入其右子树时深度就不对了

下面的两种方式等价,第一种直接对dept操作,第二中并没有更新当前的结点的dept,而是对传入的参数进行修改+1

  1. if (root->left) {
                depth++;
                traversal(root->left, depth);
                depth--; // 回溯
            }
    
  2. if (root->left) {
                traversal(root->left, depth + 1); // 隐藏着回溯
            }
    
class Solution {
	int result = 0;
	int maxDept = Integer.MIN_VALUE;//最大的深度,如果当前深度>最大深度并且为叶子,更新最大深度并且更新result
    public int findBottomLeftValue(TreeNode root) {
		travel(root,0);
		return result;
    }

	private void travel(TreeNode root, int dept){
		//因为假设二叉树中至少有一个节点,所以不必判断root是否为空
		if (root.left == null && root.right == null){
			//为叶子结点
			if (dept > maxDept){
				maxDept = dept;
				result = root.val;
			}
		}


		if (root.left != null){
			travel(root.left,dept + 1);
			//等价于
//			dept++;
//			travel(root.left,dept);
//			dept--;
		}

		if (root.right != null)
			travel(root.right,dept + 1);
	}
}

注意

		if (root.left != null)
			travel(root.left,dept + 1);
		if (root.right != null)
			travel(root.right,dept + 1);

对于这部分的代码,必须先左再右,因为要找的是最左侧的结点,也就是会先找到左侧,这样再找到右侧时只要在同一层也不会更新

112. 路径总和

力扣题目链接(opens new window)

题目

给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例: 给定如下二叉树,以及目标和 sum = 22,

在这里插入图片描述

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

解答

其实就是看递归的条件,每次递归-去当前结点的值,如果达到叶子结点值为0就返回true,否则继续找,在判断左右子树时,只有最后都找完均不满足才能返回false

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
		if (root == null)
			return false;
		return travel(root,targetSum);
    }
	private boolean travel(TreeNode root, int count){
		if (root.left == null && root.right == null){//碰到叶子结点
			if (count - root.val == 0)
				return true;
			else
				return false;
		}

		if (root.left != null){
			if (travel(root.left,count - root.val))
				return true;//找到了,返回true
		}
		if (root.right != null){
			if (travel(root.right,count - root.val))
				return true;//找到了,返回true
		}
		//只有左右子树都没找到,才返回false
		return false;
	}
}

113. 路径总和II

113.路径总和ii

题目

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例 1:

在这里插入图片描述

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

示例 2:

在这里插入图片描述

输入:root = [1,2,3], targetSum = 5
输出:[]

示例 3:

输入:root = [1,2], targetSum = 0
输出:[]

提示:

  • 树中节点总数在范围 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

解答

class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
		List<List<Integer>> result = new ArrayList<>();
		List<Integer> path = new ArrayList<>();
		if (root == null)
			return result;
		travel(root,targetSum,result,path);
		return result;
    }

	private void travel(TreeNode root, int count, List<List<Integer>> result, List<Integer> path){
		path.add(root.val);
		if (root.left == null && root.right == null){
			if (count - root.val == 0)
				result.add(new ArrayList<>(path));//result.add(path);
			return;
		}
		if (root.left != null){
			travel(root.left, count - root.val, result, path);
			path.remove(path.size() - 1);
		}

		if (root.right != null){
			travel(root.right, count - root.val, result, path);
			path.remove(path.size() - 1);
		}
	}
}

特别注意

  • 第二个函数中的result.add(new ArrayList<>(path)),只能这么写,不能写成result.add(path),因为直接将path添加到result中会导致result中的path对象发生变化,也就是说之后对path的修改会导致result也发生变化
  • 注意回溯path.remove(path.size() - 1);,只有到叶子结点后才会逐层进行删除,每次删除一个,达到回溯的效果

106.从中序与后序遍历序列构造二叉树

力扣题目链接(opens new window)

题目

根据一棵树的中序遍历与后序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

例如,给出

  • 中序遍历 inorder = [9,3,15,20,7]
  • 后序遍历 postorder = [9,15,7,20,3] 返回如下的二叉树:

在这里插入图片描述

解答

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
		//post找根,in分左右
		if (postorder.length == 0)
			return null;

		int root_val = postorder[postorder.length - 1];
		int index = -1;
		for (int i = 0; i < inorder.length; i++) {
			if (inorder[i] == root_val){
				index = i;
				break;
			}
		}
		TreeNode root = new TreeNode(root_val);//找到了中序的根

		if (postorder.length == 1)//此时是叶子结点
			return root;

		int[] leftInOrder = Arrays.copyOfRange(inorder, 0, index);
		int[] rightInOrder = Arrays.copyOfRange(inorder, index + 1, inorder.length);

		int[] leftPostOrder = Arrays.copyOfRange(postorder, 0, leftInOrder.length);
		int[] rightPostOrder = Arrays.copyOfRange(postorder, leftInOrder.length, postorder.length - 1);


		root.left = buildTree(leftInOrder,leftPostOrder);
		root.right = buildTree(rightInOrder,rightPostOrder);
		return root;
	}
}

Arrays.copyOfRange(inorder,0,index);截取的是inorder数组的索引为0到index-1的数据,左闭右开

105.从前序与中序遍历序列构造二叉树

力扣题目链接(opens new window)

题目

根据一棵树的前序遍历与中序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

例如,给出

前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树:

在这里插入图片描述

解答

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
		if (preorder.length == 0)
			return null;
		int root_val = preorder[0];
		TreeNode root = new TreeNode(root_val);
		if (preorder.length == 1)//为叶子结点
			return root;
		int index = -1;
		for (int i = 0; i < inorder.length; i++) {
			if (inorder[i] == root_val){
				index = i;
				break;
			}
		}

		int[] leftInOrder = Arrays.copyOfRange(inorder,0,index);
		int[] rightInOrder = Arrays.copyOfRange(inorder,index + 1,inorder.length);

		int[] leftPreOrder = Arrays.copyOfRange(preorder,1,leftInOrder.length + 1);
		int[] rightPreOrder = Arrays.copyOfRange(preorder,leftInOrder.length + 1,preorder.length);

		root.left = buildTree(leftPreOrder,leftInOrder);
		root.right = buildTree(rightPreOrder,rightInOrder);
		return root;
    }
}

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

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

相关文章

【ARM 嵌入式 C 常用数据结构系列 25.1 -- linux 双向链表 list_head 使用详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 内核双向链表双向链表的数据结构初始化双向链表在双向链表中添加元素遍历双向链表链表使用示例注意事项 内核双向链表 在Linux内核中&#xff0c;双向链表是一种广泛使用的数据结构&#xff0c;允许从任意节点高效地进行前向或后向…

蓝桥杯-冶炼金属(二分求最大最小)

P9240 [蓝桥杯 2023 省 B] 冶炼金属 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 二分做法&#xff1a; #include<bits/stdc.h> using namespace std; #define int long long const int N 1e410; int n,a,b; int v[N],cnt[N]; int check(int x){for(int i1;i<n;i…

写JDBC遇到的问题

执行会出现以下错误信息 java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ? and loginPwd ? at line 1 at com.mysql.cj.jdbc.exceptions…

05-延迟任务精准发布文章

延迟任务精准发布文章 1)文章定时发布 2)延迟任务概述 2.1)什么是延迟任务 定时任务&#xff1a;有固定周期的&#xff0c;有明确的触发时间延迟队列&#xff1a;没有固定的开始时间&#xff0c;它常常是由一个事件触发的&#xff0c;而在这个事件触发之后的一段时间内触发…

鸿蒙OS元服务开发:【(Stage模型)学习窗口沉浸式能力】

一、体验窗口沉浸式能力说明 在看视频、玩游戏等场景下&#xff0c;用户往往希望隐藏状态栏、导航栏等不必要的系统窗口&#xff0c;从而获得更佳的沉浸式体验。此时可以借助窗口沉浸式能力&#xff08;窗口沉浸式能力都是针对应用主窗口而言的&#xff09;&#xff0c;达到预…

LeetCode 1017. 负二进制转换

解题思路 相关代码 class Solution {public String baseNeg2(int n) {if(n0) return "0";String s"";while(n!0)if(Math.abs(n)%20){nn/(-2);ss0;}else{ss1; n (n-1)/(-2);}String t reverse(s);return t;}public String reverse(String s){Str…

C++——位图和布隆过滤器

在C中&#xff0c;哈希这种思想的应用场景有很多&#xff0c;位图就是其中的一种。 位图 位图&#xff1a;位图是一种哈希思想的产物&#xff0c;可以通过它来对数据进行快速的查找的方法&#xff0c;在位图中&#xff0c;有2种状态来表示在或者不在&#xff0c;即1/0。 位图…

vue2中的局部组件和全局组件

注&#xff1a;vue2中使用组件远没有vue3中简单&#xff0c;具体可以看阿耿老师的lingshi小程序 如图所示&#xff1a;

web学习笔记(五十二)数据库

目录 1. 数据库的相关概念 1.1 什么是数据库 1.2 常见数据库的分类 1.3 传统型数据库的数据组织结构 1.4 补充 2. 使用 SQL 管理数据库 2.1 什么是 SQL&#xff1f; 2.2 SQL 能做什么 2.3 SQL 的 SELECT 语句 2.4 SQL 的 INSERT INTO 语句 2.5 SQL 的 UPDATE 语…

MySQL批量插入,如何判断重复

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 需要把其他库或者E…

PyQt6实战6--高亮

PyQt6实战3--sql查询器-CSDN博客 在sql查询器的基础上添加了sql语法的高亮 运行效果&#xff1a; 代码&#xff1a; 只需要在原来的代码上添加一行 rightTopLayout QVBoxLayout()rightTopLayout.addWidget(QLabel("输入sql:"))self.sql QTextEdit() #加一行高亮&…

清明假期作业

1、实现文件夹的拷贝功能 注意判断被拷贝的文件夹是否存在&#xff0c;如果不存在则提前 不考虑递归拷贝的问题 #include<myhead.h> int my_copy(char* name,const char *p) {char buf[256]"./";strcat(buf,p);strcat(buf,"/");strcat(buf,name);in…

文件夹批量重命名,高效翻译支持中文转日语,轻松管理文件

在信息爆炸的时代&#xff0c;我们每天都在与大量的文件打交道。你是否曾为如何高效管理这些文件而苦恼&#xff1f;是否曾在中文与日语文件之间转换时感到无助&#xff1f;今天&#xff0c;我要为大家介绍一款神奇的工具——文件批量改名高手&#xff0c;它能帮助你批量重命名…

【C++】map set 底层刨析

文章目录 1. 红黑树的迭代器2. 改造红黑树3. map 的模拟实现4. set 的模拟实现 在 C STL 库中&#xff0c;map 与 set 的底层为红黑树&#xff0c;那么在不写冗余代码的情况下使用红黑树同时实现 map 与 set 便是本文的重点。 1. 红黑树的迭代器 迭代器的好处是可以方便遍历&…

二季度必胜!创维汽车季度营销会议探索未来新可能

总结旧岁月&#xff0c;开启新篇章。2024年4月2日&#xff0c;创维汽车召开“向死而生&#xff0c;破茧成蝶”季度营销会议。本次会议总结复盘了一季度营销团队的工作并对即将到来的二季度进行了规划部署。创维集团、创维汽车创始人黄宏生先生&#xff0c;创维汽车总裁&#xf…

算法——链表(1)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享链表专题的第一部分 如果有不足的或者错误的请您指出! 1.链表常用技巧总结 1.1引入虚拟头结点 在力扣上,基本提供的链表题目都是"无头的",但是针对无头链表,我们最…

C语言-预定义符号

编译和链接&#xff08;基础速通版&#xff09;-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/137182220 预定义符号 包含 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的…

C++从入门到精通——初步认识面向对象及类的引入

初步认识面向对象及类的引入 前言一、面向过程和面向对象初步认识C语言C 二、类的引入C的类名代表什么示例 C与C语言的struct的比较成员函数访问权限继承默认构造函数默认成员初始化结构体大小 总结 前言 面向过程注重任务的流程和控制&#xff0c;适合简单任务和流程固定的场…

R155/R156:汽车网络安全新法规快速指南

R155/R156:汽车网络安全新法规快速指南 随着国际机构进入网络安全领域,制定法规、标准和指南,公众在其使用的车辆中享受更好的网络安全保护指日可待。随着时间的推移,车辆网络安全将不断发展以应对不断变化的网络威胁。 欧洲经济委员会 (ECE) 的 R155 和 R156 法规旨在应…

Day30 线程安全之窗口售票问题(含代码)

Day30 线程安全之窗口售票问题&#xff08;含代码&#xff09; 一、需求&#xff1a; 铁道部发布了一个售票任务&#xff0c;要求销售1000张票&#xff0c;要求有3个窗口来进行销售&#xff0c; 请编写多线程程序来模拟这个效果&#xff08; 注意&#xff1a;使用线程类的方式…