Day21:Leetcode513.找树左下角的值 +112. 路径总和 113.路径总和ii + 106.从中序与后序遍历序列构造二叉树

LeetCode:513.找树左下角的值

解决方案:

1.思路

  • 在遍历一个节点时,需要先把它的非空右子节点放入队列,
  • 然后再把它的非空左子节点放入队列,这样才能保证从右到左遍历每一层的节点。
  • 广度优先搜索所遍历的最后一个节点的值就是最底层最左边节点的值。
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        int ret = 0;
        //基于数组的双端队列
        Queue<TreeNode> queue = new ArrayDeque<TreeNode>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode p = queue.poll();
            if (p.right != null) {
                queue.offer(p.right);
            }
            if (p.left != null) {
                queue.offer(p.left);
            }
            //如果当前队列不为空。当前根节点既没有左节点,也没有右节点,那么就把此该节点赋值给ret
            ret = p.val;
        }
        return ret;
    }
}

3.复杂度分析在这里插入图片描述

LeetCode:112. 路径总和

解决方案:

1.思路:

递归三部曲:

  1. 函数返回类型和参数;
  2. 终止条件;
  3. 递归逻辑

递归逻辑

2.代码实现

public class Solution {
    private boolean traversal(TreeNode cur, int count) {
        if (cur.left == null && cur.right == null && count == 0) return true; // 遇到叶子节点,并且计数为0
        if (cur.left == null && cur.right == null) return false; // 遇到叶子节点直接返回

        if (cur.left != null) { // 左
            count -= cur.left.val; // 递归,处理节点;
            if (traversal(cur.left, count)) return true;
            count += cur.left.val; // 回溯,撤销处理结果
        }
        if (cur.right != null) { // 右
            count -= cur.right.val; // 递归,处理节点;
            if (traversal(cur.right, count)) return true;
            count += cur.right.val; // 回溯,撤销处理结果
        }
        return false;
    }

    public boolean hasPathSum(TreeNode root, int sum) {
        if (root == null) return false;
        return traversal(root, sum - root.val);
    }
}

3.复杂度分析

在这里插入图片描述

LeetCode:113.路径总和ii

解决方案:

1.思路:

  • 思路同112
  • 但是注意递归函数不再有返回值,而是用一个 path数组接住;然后再用一个result数组接住所有path;

2.代码实现

public class Solution {
    private List<List<Integer>> result = new ArrayList<>();
    private List<Integer> path = new ArrayList<>();

    // 递归函数不需要返回值,因为我们要遍历整个树
    private void traversal(TreeNode cur, int count) {
        if (cur.left == null && cur.right == null && count == 0) { // 遇到了叶子节点且找到了和为sum的路径
            result.add(new ArrayList<>(path));
            return;
        }

        if (cur.left == null && cur.right == null) return; // 遇到叶子节点而没有找到合适的边,直接返回

        if (cur.left != null) { // 左 (空节点不遍历)
            path.add(cur.left.val);
            count -= cur.left.val;
            traversal(cur.left, count);    // 递归
            count += cur.left.val;        // 回溯
            path.remove(path.size() - 1); // 回溯
        }
        if (cur.right != null) { // 右 (空节点不遍历)
            path.add(cur.right.val);
            count -= cur.right.val;
            traversal(cur.right, count);   // 递归
            count += cur.right.val;       // 回溯
            path.remove(path.size() - 1); // 回溯
        }
    }

    public List<List<Integer>> pathSum(TreeNode root, int sum) {
        result.clear();
        path.clear();
        if (root == null) return result;
        path.add(root.val); // 把根节点放进路径
        traversal(root, sum - root.val);
        return result;
    }
}

3.复杂度分析

  • 时间复杂度:O(N),其中N是树中节点的数量。这是因为每个节点在递归过程中会被访问一次。尽管存在递归调用,但每个节点只被访问并处理一次,因此总体时间复杂度线性依赖于树的大小,而不是递归深度。
  • 空间复杂度:最坏情况下,当树完全不平衡,且每一条从根到叶子的路径都满足题目条件时,递归的深度达到最大,此时的空间复杂度由递归栈的深度决定,为O(N)。最好情况下(即树完全平衡),递归的最大深度为log(N),因此在这种情况下,空间复杂度为O(log(N))。但由于我们还需要存储路径(path),在最坏情况下(每条边都构成解),这也会占用O(N)的空间。因此,综合考虑,整体的空间复杂度也是O(N)。

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

解决方案:

1.思路:

  • 利用遍历特性:中序遍历(左根右)确定节点在序列中的相对位置,后序遍历(左右根)的最后一个元素总是当前子树的根节点
  • 递归思想:通过递归不断地将问题分解为更小的子问题,直到达到基础情况(空列表),然后逐层返回,逐步构建整棵树。
  • 动态调整遍历列表:每次递归调用前,根据当前子树的信息调整中序和后序遍历列表,确保传入的列表仅对应当前子树的信息。

2.代码实现

import java.util.ArrayList;
import java.util.List;

public class Solution {
    private TreeNode traversal(List<Integer> inorder, List<Integer> postorder) {
        if (postorder.size() == 0) return null;

        // 后序遍历数组最后一个元素,就是当前的中间节点
        int rootValue = postorder.get(postorder.size() - 1);
        TreeNode root = new TreeNode(rootValue);

        // 叶子节点
        if (postorder.size() == 1) return root;

        // 找到中序遍历的切割点
        int delimiterIndex;
        for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
            if (inorder.get(delimiterIndex) == rootValue) break;
        }

        // 切割中序数组
        List<Integer> leftInorder = new ArrayList<>(inorder.subList(0, delimiterIndex));
        List<Integer> rightInorder = new ArrayList<>(inorder.subList(delimiterIndex + 1, inorder.size()));

        // postorder 舍弃末尾元素
        postorder.remove(postorder.size() - 1);

        // 切割后序数组
        List<Integer> leftPostorder = new ArrayList<>(postorder.subList(0, leftInorder.size()));
        List<Integer> rightPostorder = new ArrayList<>(postorder.subList(leftInorder.size(), postorder.size()));

        root.left = traversal(leftInorder, leftPostorder);
        root.right = traversal(rightInorder, rightPostorder);

        return root;
    }

    public TreeNode buildTree(List<Integer> inorder, List<Integer> postorder) {
       if (inorder.size() == 0 || postorder.size() == 0) return null;
        return traversal(inorder, postorder);
    }
}

3.复杂度分析

  • 时间复杂度:尽管递归深度会影响栈的空间复杂度,但从时间复杂度的角度看,每个节点都会导致一次遍历操作和一次分割操作,总的时间复杂度与树中节点数量成正比,即O(n)。这里的n代表树中节点的总数。
  • 空间复杂度:该算法的时间复杂度为O(n),空间复杂度在最坏情况下也是O(n),主要是由于递归调用栈的深度可能达到O(n)。在实际应用中,若二叉树较为平衡,空间复杂度可以视为O(log n)

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

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

相关文章

Amesim基础篇-元件详解-流体库管路

1 流体类型选择 如下图1所示&#xff0c;流体可以选择流体库中自带的流体。常用的流体类型为50%乙二醇溶液&#xff08;EG50W50 coolant&#xff09;。 2 管路 该模型是常用的管路&#xff0c;如下图所示。如之前所讲的建模原则&#xff1a;严格遵循R-C-R-C的原则。下图中的管…

Golang | Leetcode Golang题解之第98题验证二叉搜索树

题目&#xff1a; 题解&#xff1a; func isValidBST(root *TreeNode) bool {stack : []*TreeNode{}inorder : math.MinInt64for len(stack) > 0 || root ! nil {for root ! nil {stack append(stack, root)root root.Left}root stack[len(stack)-1]stack stack[:len(s…

领域知识 | 智能驾驶安全领域部分常见概论

Hi&#xff0c;早。 最近想买个新能源车&#xff0c;这个车吧相比于之前的内燃车&#xff0c;新能源车与外界的交互多了很多。比如娱乐的第三方应用&#xff0c;OTA升级等应用。 交互带来的便利越多&#xff0c;暴露的风险自然也就越大&#xff0c;相比于手机等消费者终端设备…

Linux信号:信号的保存

目录 一、信号在内核中的表示 二、sigset_t 2.1sigset_t的概念和意义 2.2信号集操作数 三、信号集操作数的使用 3.1sigprocmask 3.2sigpending 3.3sigemptyset 四、代码演示 一、信号在内核中的表示 实际执行信号的处理动作称为信号 递达(Delivery) 。 信号从产生到递达…

如何使用WindowsSpyBlocker防止Windows系统被恶意监控和跟踪

关于WindowsSpyBlocker WindowsSpyBlocker是一款功能强大的Windows系统安全防护工具&#xff0c;该工具基于Go语言开发&#xff0c;WindowsSpyBlocker以一个单独的可执行程序发布&#xff0c;可以帮助广大用户防止自己的Windows系统被恶意监控和跟踪。 WindowsSpyBlocker能够利…

【手势识别-UIPinchGestureRecognizer捏合-UIPanGestureRecognizer缩放 Objective-C语言】

一、接下来,我们来说这个捏合,和,这个缩放啊 1.捏合, 首先呢,步骤,也都是一样的啊, 1)创建手势对象 2)添加手势 3)实现手势方法 pinch:捏合 UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:(id) action:(SEL)]; U…

使用大模型结合Mermaid实现业务流程图快速生成

一、需求描述 在日常系统研发过程中&#xff0c;经常面临前期要写投标技术文档&#xff0c;中期要写系统概要设计、详细设计等各类文档&#xff0c;最耗时间的便是画一些业务流程图。随着大模型的不断普及&#xff0c;大模型对文字的处理越来越强&#xff0c;现可以找一个能简化…

MySQL主从复制+读写分离(ShardingJDBC)

MySQL主从复制读写分离 MySQL主从复制介绍二进制日志&#xff1a; MySQL的主从复制原理如下搭建主从复制准备工作主库配置从库配置 测试 读写分离案例ShardingJDBC介绍数据库环境初始工程导入读写分离配置测试1). 保存数据2). 修改数据3). 查询数据4). 删除数据 MySQL主从复制 …

LVS精益价值管理系统 DownLoad.aspx 任意文件读取漏洞复现

0x01 产品简介 LVS精益价值管理系统是杭州吉拉科技有限公司研发的一款专注于企业精益化管理和价值流优化的解决方案。该系统通过集成先进的数据分析工具、可视化的价值流映射技术和灵活的流程改善机制&#xff0c;帮助企业实现高效、低耗、高质量的生产和服务。 0x02 漏洞概述…

Java ( 框架界面 , 按钮 , 动作监听ActionListener ,鼠标监听MouseListener,键盘监听KeyListener)的使用方法

package 拼图阶段任务.ui;import javax.swing.*; import java.awt.*; import java.awt.event.*;public class UseMethod {public static void main(String[] args) { // 框架的用法JFrame jf new JFrame();// 设置界面的宽高jf.setSize(603,680);// 设置界面的标题jf.setTitle…

Redis的下载、安装、启动和初尝试【超级简单】

redis最好是在Linux系统中使用&#xff0c;这是最接近生产实际的环境。 不过&#xff0c;我们初学者&#xff0c;目的是学习Redis的使用、原理&#xff0c;如果在Linux下直接学习Redis&#xff0c;很可能会因为命令不熟悉而劝退&#xff0c;这是不好的。 因此&#xff0c;我主张…

国际货币基金组织警告:网络攻击影响全球金融稳定

近日&#xff0c;在一份关于金融稳定的报告中&#xff0c;国际货币基金组织&#xff08;IMF&#xff09;用了一章&#xff08;共三章&#xff09;的篇幅描述了网络攻击对金融环境的影响&#xff0c;并警告称&#xff0c;全球金融稳定正受到日益频繁和复杂的网络攻击的威胁。同时…

kubernetes(k8s) v1.30.1 创建本地镜像仓库 使用本地docker镜像仓库部署服务 Discuz X3.5 容器搭建论坛

1 master11创建本地镜像仓库 [rootmaster11 ~]# docker run -d -p 5000:5000 --restartalways --name registry registry:2 Unable to find image registry:2 locally 2: Pulling from library/registry 79e9f2f55bf5: Pull complete 0d96da54f60b: Pull complete 5b27040df…

是德科技 DSOS104A MSOS104A示波器

产品 带宽 通道数 最大存储器深度 DSOS104A 高清晰度示波器 1 GHz 4 个模拟通道 800 Mpts MSOS104A 高清晰度示波器 1 GHz 4 个模拟通道和 16 个数字通道 800 Mpts 商品介绍 …

ELK 日志监控平台(一)- 快速搭建

文章目录 ELK 日志监控平台&#xff08;一&#xff09;- 快速搭建1.ELK 简介2.Elasticsearch安装部署3.Logstash安装部署4.Kibana安装部署5.日志收集DEMO5.1.创建SpringBoot应用依赖导入日志配置文件 logback.xml启动类目录结构启动项目 5.2.创建Logstash配置文件5.3.重新启动L…

锁相环的一些学习笔记--(1)

下图两组1.2.3可以对应起来&#xff1b; 参考资料&#xff1a; 1. Matlab https://www.bilibili.com/video/BV1bR4y1Z7Xg/?spm_id_from333.1296.top_right_bar_window_history.content.click&vd_source5556680656536651c49f5e55d7d4df23 2. https://www.bilibili.com/…

Hadoop开发之JavaAPI操作HDFS

目录 一、maven的安装与配置1.maven的下载2.maven的安装与配置&#xff08;1&#xff09;解压&#xff08;2&#xff09;创建本地仓库文件夹&#xff08;3&#xff09;修改settings.xml配置文件&#xff08;4&#xff09;配置maven的环境变量&#xff08;5&#xff09;idea中ma…

将list对象里的某一个属性取出组成一个新的list

使用Java8将对象里的某一个属性取出组成一个新的list List<Spgg1> listnew ArrayList<>();Spgg1 spgg1new Spgg1();spgg1.setSpdm("测试");spgg1.setGgdm("001");list.add(spgg1);Spgg1 spgg2new Spgg1();spgg2.setSpdm("测试2");sp…

不用从头训练,通过知识融合创建强大的统一模型

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的开发和训练是一个复杂且成本高昂的过程。数据需求是一个主要问题&#xff0c;因为训练这些模型需要大量的标注数据来保证其准确性和泛化能力&#xff1b;计算资源也是一个…

基于 Prometheus 的超算弹性计算场景下主机监控最佳实践

作者&#xff1a;左知 超算场景的业务特点 主机监控&#xff0c;或许是监控/可观测领域最传统和普遍的需求。在超算训练&#xff0c;AI 大规模训练的业务场景下&#xff0c;主机监控又有哪些痛点和难点呢&#xff1f;根据我们针对多个大规模超算客户的需求整理&#xff0c;超…