代码随想录【Day17】| 513. 找树左下角的值、112. 路径总和、构造二叉树(前+中,中+后)

news2024/11/17 3:51:04

513. 找树左下角的值

题目链接

题目描述:
给定一个二叉树,在树的最后一行找到最左边的值。

示例 1:
在这里插入图片描述
示例2:
在这里插入图片描述

难点:
递归法

思路:
这题要找

  1. 最底层
  2. 最左边

很容易就想到层序遍历

递归法的话,有点复杂
要向左找到最大深度,那么“左”比“右”先遍历,前中后序遍历都可以

时间复杂度:O()
空间复杂度:O()

//使用层序遍历,最下面一层的第一个就是要找的
class Solution {
    public int findBottomLeftValue(TreeNode root) {
        Deque<TreeNode> que = new ArrayDeque<>();
        int res = 0;
        que.addLast(root);
        while(!que.isEmpty()) {
            int len = que.size();
            for (int i = 0; i < len; i++) {
                TreeNode cur = que.removeFirst();
                if (i == 0) res = cur.val; //记录当前层最左侧元素
                if (cur.left != null) que.addLast(cur.left);
                if (cur.right != null) que.addLast(cur.right);
            }
        }
        return res;
    }
}

//递归法
class Solution {
    int maxDepth = 0;
    int result = Integer.MAX_VALUE;
    public int findBottomLeftValue(TreeNode root) {
        result = root.val;
        traversal(root, 0);
        return result;
    }

    private void traversal(TreeNode root, int depth) {
        if (depth > maxDepth) { //遇到更大的深度就更新(因为“左”比“右”先遍历,所以深度下探最先访问左边的结点)
            maxDepth = depth;
            result = root.val;
        }

        if (root.left != null) {
            traversal(root.left, depth+1);
        }

        if (root.right != null) {
            traversal(root.right, depth+1);
        }
    }
}

时长:
20min

收获:
递归法的分析练习

还可以练习,优先掌握递归法:
110. 平衡二叉树
257. 二叉树的所有路径


112. 路径总和

题目链接

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

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

示例: 给定如下二叉树,以及目标和 sum = 22,
在这里插入图片描述
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

提示:
树中节点的数目在范围 [0, 5000] 内
-1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000

难点:
注意题目中结点的值是可以为负数的~~~

思路:
看到这题马上想到应该用递归会更好写一些
就用前序遍历吧~

要判断和targetSum的关系,递归函数中就需要有当前总和curSum
在单层递归中,要判断是否找到了叶子结点
如果找到叶子,判断总和是否相同

时间复杂度:O()
空间复杂度:O()

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) return false;
        int curSum = 0;
        return traversal(root, curSum, targetSum);
    }

    private boolean traversal(TreeNode root, int curSum, int targetSum) {
        if (root == null) return false;
        curSum += root.val;
        if (root.left == null && root.right == null) { //遍历到叶子节点
            if (curSum == targetSum) {
                return true;
            }else {
                return false;
            }
        }
        //左右子树只要有满足条件的路径就返回
        return traversal(root.left, curSum, targetSum) || traversal(root.right, curSum, targetSum);
    }
}

参考代码随想录还有更简洁的方法,其实这个减法思想在两数之和就接触到过,注意消化:

class solution {
   public boolean 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) {
            boolean left = haspathsum(root.left, targetsum);
            if (left) {      // 已经找到
                return true;
            }
        }
        if (root.right != null) {
            boolean right = haspathsum(root.right, targetsum);
            if (right) {     // 已经找到
                return true;
            }
        }
        return false;
    }
}

// 简洁方法
class solution {
    public boolean haspathsum(treenode root, int targetsum) {
        
        if (root == null) return false; // 为空退出
        
        // 叶子节点判断是否符合
        if (root.left == null && root.right == null) return root.val == targetsum;

        // 求两侧分支的路径和
        return haspathsum(root.left, targetsum - root.val) || haspathsum(root.right, targetsum - root.val);
    }
}

时长:
12min

收获:
求目标总和的减法思维

可以练习:
113. 路径总和 II


构造二叉树

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

难点:
找到切分点,递归地去构造,注意区间划分要准确,统一开闭

思路:

//中序+后序 构造二叉树
class Solution {
    Map<Integer, Integer> map;  // 方便根据数值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前闭后开
    }
    
    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 参数里的范围都是前闭后开
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int delimiterIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍历的最后一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[delimiterIndex]);  // 构造结点
        int lenOfLeft = delimiterIndex - inBegin;  // 保存中序左子树个数,用来确定后序数列的个数
        root.left = findNode(inorder, inBegin, delimiterIndex,
                            postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, delimiterIndex + 1, inEnd,
                            postorder, postBegin + lenOfLeft, postEnd - 1);
        return root;
    }
}

//前序+中序 构造二叉树
class Solution {
    Map<Integer, Integer> map;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
            map.put(inorder[i], i);
        }

        return findNode(preorder, 0, preorder.length, inorder,  0, inorder.length);  // 前闭后开
    }

    public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {
        // 参数里的范围都是前闭后开
        if (preBegin >= preEnd || inBegin >= inEnd) {  // 不满足左闭右开,说明没有元素,返回空树
            return null;
        }
        int delimiterIndex = map.get(preorder[preBegin]);  // 找到前序遍历的第一个元素在中序遍历中的位置
        TreeNode root = new TreeNode(inorder[delimiterIndex]);  // 构造结点
        int lenOfLeft = delimiterIndex - inBegin;  // 保存中序左子树个数,用来确定前序数列的个数
        root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft + 1,  
                            inorder, inBegin, delimiterIndex);
        root.right = findNode(preorder, preBegin + lenOfLeft + 1, preEnd,
                            inorder, delimiterIndex + 1, inEnd);
        return root;
    }
}

时长:
20min

收获:
先构造map,每次查找直接可以获取到根节点的位置
比每次遍历整个数组找切分结点要方便~

前序和中序可以唯一确定一棵二叉树。

后序和中序可以唯一确定一棵二叉树。

那么前序和后序可不可以唯一确定一棵二叉树呢?

前序和后序不能唯一确定一棵二叉树!,因为没有中序遍历无法确定左右部分,也就是无法分割。

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

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

相关文章

Cosmos NDP编程框架(easyNDP)说明文档

Cosmos NDP编程框架(easyNDP)说明 更新时间&#xff1a;2023-2-17 作者&#xff1a;Gary 一.简介 本文档主要用于说明本简易NDP框架——easyNDP framework的架构、开发新应用以及使用的方法。 在开始前&#xff0c;有一个概念需要提前说明&#xff0c;文档中的块这个概念&…

YOLO-V5 系列算法和代码解析(八)—— 模型移植

文章目录工程目标芯片参数查阅官方文档基本流程Python 版工具链安装RKNPU2的编译以及使用方法移植自己训练的模型工程目标 将自己训练的目标检测模型【YOLO-V5s】移植到瑞芯微【356X】芯片平台&#xff0c;使用C推理&#xff0c;最终得到预期的结果。 芯片参数 芯片参数介绍…

IOS 自动化测试环境搭建

购买MacPDD 比TB JD 便宜500&#xff0c;下单安装homebrew/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装npm cnpmbrew install node; npm install -g cnpm --registryhttps://registry.npm.taobao.org;安装类似Andro…

Windows平台使用gdb连接qemu虚拟机上的系统

先安装MinGW&#xff1b; 除了gcc、g&#xff0c;把gdb也选上&#xff1b;可能选第一个就可以了&#xff0c;不清楚把后面几个也选上&#xff1b; 安装完成看一下gcc, g&#xff0c;gdb&#xff0c;编译工具和调试器都有了&#xff1b; 把bin目录加到环境变量&#xff1b; 看一…

element-ui实现动态添加表单项并实现事件触发验证验证

需求分析&#xff1a;点击新增后新增一个月度活动详情&#xff0c;提交时可同时提交多个月度活动详情。点击某一个月度活动信息的删除后可删除对应月度活动信息 H5部分&#xff1a; <el-dialog :title"title" :visible.sync"open" append-to-body>…

数据结构时间空间复杂度笔记

&#x1f57a;作者&#xff1a; 迷茫的启明星 本篇内容&#xff1a;数据结构时间空间复杂度笔记 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;家人们&#xff0c;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤…

基础篇—CSS margin(外边距)解析

什么是CSS margin(外边距)? CSS margin(外边距)属性定义元素周围的空间。 属性描述margin简写属性。在一个声明中设置所有外边距属性。margin-bottom设置元素的下外边距。margin-left设置元素的左外边距。margin-right设置元素的右外边距。margin-top设置元素的上外边距。mar…

Linux 磁盘配额与VDO技术

目录 磁盘容量限额quota技术 磁盘配额分类 对磁盘开启限额服务 xfs_quota管理磁盘配额 edquota 管理磁盘配额 VDO虚拟数据优化 创建VDO卷 vdostats 查看vdo卷的使用情况 磁盘容量限额quota技术 磁盘配额可以限制用户的硬盘可用容量和用户所能创建的最大文件个数 磁盘…

2023美赛 ICM E题详细版思路

问题E&#xff1a;光污染注&#xff1a;楷体为题目原文&#xff0c;宋体为思路部分首先&#xff0c;我们需要考虑的就是美赛ABEF的核心问题&#xff0c;数据。这里E题是以光污染为背景的题目&#xff0c;首当其冲的我们就需要收集一些数据以支撑我们的模型。对于E题提出的问题&…

Allegro如何更改DRC尺寸大小操作指导

Allegro如何更改DRC尺寸大小操作指导 在做PCB设计的时候,DRC可以辅助设计,有的时候DRC的尺寸过大会影响视觉,Allegro支持将DRC的尺寸变小或者改大 如下图,DRC尺寸过大 如何改小,具体操作如下 点击Setup选择Design Parameters

结构体——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰的内容是结构体噢&#xff0c;之前我们在初始C语言中其实就已经学习过了结构体的知识&#xff0c;但是不是很全面&#xff0c;这次&#xff0c;我们也只是稍微详细一点&#xff0c;敬请期待小雅兰之后的博客&#xff…

分享五款功能简单粗暴的小软件

今天分享几款功能简单的小软件&#xff0c;小伙伴们们可以来看一下有没有你需要的功能软件。 1.书签管理工具——Toby for Chrome Toby是一个特别有用的浏览器书签管理工具。使用它&#xff0c;您可以创建自己的不同类别的书签。比如在工作生活等方面&#xff0c;学习常用的查…

操作系统(进程管理)

一、进程的定义及特征进程的定义由程序、数据、进程控制块三部分组成为了使程序可以并发执行&#xff0c;且可以对并发执行的程序加以描述和控制。不同角度的定义&#xff1a;进程是程序的一次执行&#xff1b;进程是一个程序及其数据在处理机上顺序执行时所发生的活动&#xf…

js实现元素样式切换的基本功能

需求&#xff1a;用户第一次点击某些元素&#xff0c;改变元素的某些样式&#xff0c;比如背景颜色&#xff0c;字体颜色。用户第二次点击某些元素&#xff0c;恢复之前的样式。.....思路&#xff1a;准备一定量的div盒子&#xff0c;并取相同的类名<div class"box&quo…

2022年襄阳中级工程师职称水平能力测试成绩出来了吗?

2022年下半年襄阳水平能力测试考试在2月初举行的&#xff0c;目前襄阳水测成绩已出&#xff0c;合格标准已出&#xff0c;襄阳水测今年合格标准是50分及格&#xff0c;以前是30多分及格&#xff0c;今年合格标准突然上涨蛮多&#xff0c;不过大家考的还是不错&#xff0c;分享一…

STC单片机 VS/HX1838红外接收和发送实验

STC单片机 VS/HX1838红外接收和发送实验 📌相关篇《STC单片机获取红外解码从串口输出》🔨所使用的红外接收头VS1838 📋VS1838引脚定义🌿5MM发射头,940nm红外发射二极管 红外遥控发射头。(外观看起来和普通的发光二极管没有什么差异,购买时需要注意确认)。 🔰采用的…

XXL-JOB分布式任务调度框架(二)-路由策略

文章目录1.引言2.任务详解2.1.执行器2.2.基础配置3.路由策略(第一个)-案例4.路由策略(最后一个)-案例5.轮询策略-案例7.分片广播任务1.引言 本篇文章承接上文《XXL-JOB分布式任务调度框架(一)-基础入门》&#xff0c;上一次和大家简单介绍了下 xxl-job 的由来以及使用方法&…

【Node.js】全局可用变量、函数和对象

文章目录前言_dirname和_filename变量全局函数setTimeout(cb,ms)clearTimeout(t)setInterval(cb,ms)clearInterval(t)setImmediate(cb)clearImmediate()console对象console.info([data][,...])console.error([data][,...])console.warn([data][,...])console.dir(obj[,options]…

【Linux 多线程互斥】如何保证锁的原子性(互斥的原理)

临界资源:可以被多个执行流&#xff08;线程或者叫轻量级进程&#xff09;同是访问的&#xff08;多个执行流共享的&#xff0c;比如&#xff1a;全局、堆等等&#xff09;&#xff1b;临界区&#xff1a;访问这些临界资源的代码&#xff1b;原子性&#xff1a;没有中间态&…

vue动画

vue动画 1.vue动画&#xff08;transition &#xff09; 使用 组件 组件可以用来添加过渡效果&#xff0c;当一个元素或组件被插入或删除时&#xff0c;它会自动应用过渡效果。 name 属性用于指定具体是那个动画生效&#xff0c;如果不加默认是v-开头的 <!-- 可以添加指定的…