代码随想录算法训练营第十八天|513. 找树左下角的值|112. 路径总和|106. 从中序与后序遍历序列构造二叉树

news2025/1/16 15:50:43

513. 找树左下角的值

题目:给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。

示例 1:请添加图片描述

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

思路一:层序遍历,最后一层的第一个元素,即是树左下角的值。
思路二:通过递归,深度优先遍历原则,因为本题没有 中间节点的处理逻辑,所以使用前、中、后序遍历都可以,保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值


思路一:层序遍历
C#代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public int FindBottomLeftValue(TreeNode root) {
        var result = 0;
        if(root == null) return result;
        var queue = new Queue<TreeNode>();
        queue.Enqueue(root);
        while(queue.Any()){
            int len = queue.Count;
            var itemList = new Queue<int>();
            while(len>0){
                var temp = queue.Dequeue();
                itemList.Enqueue(temp.val);
                if(temp.left!=null) queue.Enqueue(temp.left);
                if(temp.right!=null) queue.Enqueue(temp.right);
                len--;
            }
            result = itemList.Dequeue();
        }
        return result;
    }
}

思路二:递归
C#代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    //结果值
    int result = 0;
    //最大深度
    int maxDepth = -1;
    public int FindBottomLeftValue(TreeNode root) {
        Traversal(root,1);
        return result;
    }
    // 1. 确定返回值和参数
    public void Traversal(TreeNode node,int depth){
        //2. 确定终止条件
        if(node.left==null&&node.right== null){
            //叶子节点
            if(depth>maxDepth){//当前深度大于最大深度
                maxDepth = depth;//记录当前深度为最大深度
                result = node.val;
            }
        }
        //找左下角的值所以优先遍历左左子树
        if(node.left!=null){
            depth++;
            Traversal(node.left,depth);
            //回溯深度的值
            depth--;
            //精简代码 traversal(root->left, depth + 1);  隐藏着回溯
        }
        //遍历右子树
        if(node.right!=null){
            depth++;
            Traversal(node.right,depth);
            depth--;
        }
    }
}

112. 路径总和

题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。
示例一:请添加图片描述

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

思路:可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树

C#代码:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left;
 *     public TreeNode right;
 *     public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
public class Solution {
    public bool HasPathSum(TreeNode root, int targetSum) {
        if(root == null) return false;
        targetSum -= root.val;
        //确定终止条件
        if(root.left == null && root.right == null){
            return targetSum == 0;
        }
        if(root.left!=null){
            if(HasPathSum(root.left,targetSum)) return true;
        }
        if(root.right!=null){
            if(HasPathSum(root.right,targetSum)) return true;
        }
        return false;
    }
}

113. 路径总和 II

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

叶子节点 是指没有子节点的节点。
示例一:请添加图片描述

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

C#代码:

public class Solution {
    List<IList<int>> result = new List<IList<int>>();
    public IList<IList<int>> PathSum(TreeNode root, int targetSum) {
        var list = new List<int>();
        Traversal(root,targetSum,list);
        return result;
    }
    public void Traversal(TreeNode root, int targetSum,List<int> list){
        if(root == null) return;
        list.Add(root.val);
        targetSum -= root.val;
        //到达叶子节点并且路径正确
        if(root.left==null&&root.right==null&&targetSum==0){
            result.Add(new List<int>(list.ToArray()));
            return;
        }
        if(root.left!=null){
            Traversal(root.left,targetSum,list);
            //回溯
            list.RemoveAt(list.Count - 1);
        }
        if(root.right!=null){
            Traversal(root.right,targetSum,list);
            //回溯
            list.RemoveAt(list.Count - 1);
        }
    }
}

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

题目:给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例一:请添加图片描述

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

思路:

  • 通过后序序列可以知道最后一个元素为根结点。
  • 知道根结点后,通过中序序列可以判断出根结点的左右子树。

解题过程:

  • 第一步:如果数组大小为零的话,说明是空节点了。
  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
  • 第五步:切割后序数组,切成后序左数组和后序右数组
  • 第六步:递归处理左区间和右区间

C#代码,递归

public class Solution {
    public TreeNode BuildTree(int[] inorder, int[] postorder) {
        // 1. 如果后序数组元素为0,则为空树
        if(postorder.Length==0) return null;
        // 2. 取后序序列的最后一个元素,得到根结点
        int rootVale = postorder[postorder.Length - 1];
        TreeNode node = new TreeNode(rootVale);
        if(postorder.Length == 1) return node;
        // 3. 通过根结点找到中序序列的分割点下标
        int index;
        for(index = 0; index<inorder.Length; index++){
            if(inorder[index] == rootVale){
                break;
            }
        }
        // 4. 分割左子树
        //左子树的中序序列
        int[] leftInorder = new int[index];
        //遍历拷贝
        // for(int i = 0;i<leftInorder.Length;i++){
        //     leftInorder[i] = inorder[i];
        // }
        //使用Array.Copy方法
        Array.Copy(inorder,0,leftInorder,0,leftInorder.Length);
        int[] leftPostorder = new int[leftInorder.Length];
        // for(int i= 0; i<leftPostorder.Length;i++){
        //     leftPostorder[i] = postorder[i];
        // }
        Array.Copy(postorder,0,leftPostorder,0,leftPostorder.Length);
        // 5. 分割右子树
        //右子树的中序序列
        int[] rightInorder = new int[inorder.Length -(index+1)];
        // for(int i = 0;i<rightInorder.Length;i++){
        //     rightInorder[i] = inorder[i+index+1];
        // }
        Array.Copy(inorder,index+1,rightInorder,0,rightInorder.Length);
        int[] rightPostorder = new int[rightInorder.Length];
        // for(int i = 0;i<rightPostorder.Length;i++){
        //     rightPostorder[i] = postorder[i+leftPostorder.Length];
        // }
        Array.Copy(postorder,leftPostorder.Length,rightPostorder,0,rightPostorder.Length);
        // 6. 递归左区间和右区间
        node.left = BuildTree(leftInorder,leftPostorder);
        node.right = BuildTree(rightInorder,rightPostorder);
        return node;
    }
}

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

题目:给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例一:请添加图片描述

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

思路和后序遍历一样,通过前序遍历的第一个元素可知根结点,通过根结点和中序序列,分割出左右子树,通过递归即可构建出二叉树。

C#代码:

public class Solution {
    public TreeNode BuildTree(int[] preorder, int[] inorder) {
        //1. 判断前序遍历长度
        if(preorder.Length == 0) return null;
        //2. 获取根结点
        int rootVale = preorder[0];
        TreeNode root = new TreeNode(rootVale);
        if(preorder.Length == 1) return root;
        //3. 获取根结点在中序序列中的下标
        int index;
        for(index = 0;index<inorder.Length;index++){
            if(inorder[index] == rootVale){
                break;
            }
        }
        //4. 分割左子树
        int[] leftInorder = new int[index];
        Array.Copy(inorder,0,leftInorder,0,index);
        int[] leftPreorder = new int[leftInorder.Length];
        Array.Copy(preorder,1,leftPreorder,0,leftPreorder.Length);
        //5. 分割右子树
        int[] rightInorder = new int[inorder.Length -(index+1)];
        Array.Copy(inorder,index+1,rightInorder,0,rightInorder.Length);
        int[] rigthPreorder = new int[rightInorder.Length];
        Array.Copy(preorder,1+leftPreorder.Length,rigthPreorder,0,rigthPreorder.Length);
        //6. 递归左区间和右区间
        root.left = BuildTree(leftPreorder,leftInorder);
        root.right = BuildTree(rigthPreorder,rightInorder);
        return root;
    }
}

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

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

相关文章

【GAMES202】Real-Time Ray Tracing 1—实时光线追踪1

一、前言 这篇我们开始新的话题—Real-Time Ray Tracing简称RTRT&#xff0c;也就是实时光线追踪&#xff0c;关于光线追踪&#xff0c;我们已经不止一次提到过它的优点&#xff0c;无论是软阴影还是全局光照&#xff0c;光线追踪都很容易做&#xff0c;唯一的缺点就是速度太慢…

时空预测 | 线性时空预测模型、图时空预测

目录 线性时空预测图时空预测 线性时空预测 这篇文章在时空预测领域&#xff0c;搭建了一个简单高效的线性模型&#xff0c;且使用了channel-independence的方式进行建模。 模型的整体结构如下图所示&#xff0c;是一个级联的结构。输入分为三个部分&#xff1a;temporal embed…

java的动态代理如何实现

一. JdkProxy jdkproxy动态代理必须基于接口(interface)实现 接口UserInterface.java public interface UserService {String getUserName(String userCde); }原始实现类&#xff1a;UseServiceImpl.java public class UserServiceImpl implements UserSerice {Overridepub…

布局过程的完全解析

前言 那么为什么要分为两个流程呢 因为测量流程是一个复杂的流程&#xff0c;有时候不一定一遍就能得出测量结果&#xff0c;可能需要 2 - 3 次甚至更多 自定义布局的几种类型&#xff0c;也是自定义布局的两个方法 实战&#xff0c;第一种类型&#xff1a;改写已有View 的步骤…

day34 Map Properties

Map<String,Integer> map new HashMap<>(); map.put("a",1);map.put("b",2);map.put("c",3);map.put("d",4);Integer a map.put("a", 2);System.out.println(a);Integer chinese map.put("语文",1…

新一代G7系列浪潮云海超融合EC纠删功能设计

浪潮云海在2023年5月正式发布新一代InCloud Rail G7系列超融合一体机&#xff0c;其内置的InCloud dSAN超融合存储组件&#xff0c;基于新一代的硬件平台设计&#xff0c;支持全栈RDMA协议&#xff0c;同时在EC纠删功能上也带来全新体验&#xff0c;为新时代用户提供更丰富的产…

PYTHON(一)——认识python、基础知识

一、为什么要学习python&#xff1f; Python 被认为是人工智能、机器学习的首选语言&#xff0c;可以说是全世界最流行通用范围最广的语言&#xff0c;几乎可以完成所有的任务&#xff0c;像设计游戏、建网站、造机器人甚至人工智能等都广泛使用Python。 二、输出&#xff08;…

注解-宋红康

目录 一、注解&#xff08;Annotation&#xff09;概述二、常见的注解实例三、如何自定义注解四、JDK中的四个元注解五、Java8注解的新特性1、可重复注解2、类型注解 一、注解&#xff08;Annotation&#xff09;概述 二、常见的注解实例 三、如何自定义注解 自定义注解必须配…

查询硬盘序列号、物理地址及对应批处理命令

首先说明&#xff1a; 通过winR -> cmd -> diskpart -> list disk -> select disk 0 -> detail disk -> 然后显示磁盘ID等&#xff0c;这不是序列号&#xff0c;只是磁盘ID而已。 查询序列号命令很简单&#xff1a; wmic diskdrive get serialnumber或者 w…

权限、认证与授权

权限、认证与授权 1、权限概述 &#xff08;1&#xff09;什么是权限 权限管理&#xff0c;一般指根据系统设置的安全策略或者安全规则&#xff0c;用户可以访问而且只能访问自己被授权的资源&#xff0c;不多不少。权限管理几乎出现在任何系统里面&#xff0c;只要有用户和…

webstorm HbuilderX工具未配置

问题&#xff1a;调试动迁uni app h5项目&#xff0c;报错 webstorm是换了电脑新安装&#xff0c; HBuilerx是从旧电脑拷贝过来的解压的文件 解决&#xff1a; 把uniapp插件&#xff0c;卸载 再重启webstorm,重装安装uniapp Tool&#xff0c; 安装第一个&#xff0c;免费。…

拓展外部SRAM

外部拓展芯片 IS62WV51216A 芯片手册 支持高速时钟通道时间为45、55ns 芯片引脚定义 通道时序 读定义表 一个纵列表示当前使用的高速通道的时间&#xff0c;选一个纵列作为参数标准。 地址控制读时序 如图&#xff0c;大概需要三个参数 写时序定义表 还是选择55ns参数 写…

数据接口工程对接BI可视化大屏(五)数据接口发布

文章目录 第5章 数据接口发布5.1 编写Service5.2 从MySQL中返回数据5.2.*1 封装Bean5.2.*2 编写Mapper5.2.3 编写ServiceImpl5.2.4 编写Controller5.2.5 测试 5.3 从Redis中返回数据5.3.1 封装Bean5.3.2 编写Mapper5.3.3 编写ServiceImpl5.3.4 编写Controller5.3.5 测试 5.4 从…

day34 Set

概述 Set也是集合Collection接口的子接口 Set也是集合Collection接口的子接口 特点&#xff1a;不保证元素有顺序&#xff0c;数组元素不可以重复 HashSet: 底层是基于HashMap的。元素是无序的。元素不可重复&#xff0c;去重机制是依据hashCode()和equals()方法 LinkedHas…

数据结构-堆的实现及应用(堆排序和TOP-K问题)

数据结构-堆的实现及应用[堆排序和TOP-K问题] 一.堆的基本知识点1.知识点 二.堆的实现1.堆的结构2.向上调整算法与堆的插入2.向下调整算法与堆的删除 三.整体代码四.利用回调函数避免对向上和向下调整算法的修改1.向上调整算法的修改2.向下调整算法的修改3.插入元素和删除元素函…

vue学习之列表渲染

列表渲染 创建 demo8.html,内容如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</…

LeetCode算法心得——判断能否在给定时间到达单元格(动态模拟)

大家好&#xff0c;我是晴天学长&#xff0c;这是一个动态模拟题&#xff0c;跟大佬相比&#xff0c;我的有点繁琐了&#xff0c;但是也算是锻炼到自己的一些细节问题&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。 1) .判断能否在给定时间到达单元…

Pytorch面试题整理(2023.09.10)

1、pytorch如何微调fine tuning&#xff1f; 在加载了预训练模型参数之后&#xff0c;需要finetuning 模型&#xff0c;可以使用不同方式finetune。 局部微调&#xff1a;加载了模型参数后&#xff0c;只想调节最后几层&#xff0c;其他层不训练&#xff0c;也就是不进行梯度…

【Endnote】如何出现“作者(年份) found that ....”的格式?

如何出现“作者&#xff08;年份&#xff09; found that ....”的格式&#xff1f; 非常简单&#xff01;先用endnote插入文献后&#xff0c;默认显示&#xff1a; 然后&#xff0c;重点来了&#xff0c;点开这个&#xff1a; 然后&#xff0c;将此处的default改成Display as…

unique_ptr的大小探讨

unique_ptr大小和删除器有很大关系&#xff0c;具体区别看如下代码的分析。不要让unique_ptr占用的空间太大&#xff0c;否则不会达到裸指针同样的效果。 #include <iostream> #include <memory> using namespace std;class Widget {int m_x;int m_y;int m_z;publ…