代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和

代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和

文章目录

  • 代码随想录算法训练营第十四天 | 110.平衡二叉树、257.二叉树的所有路径、404.左叶子之和
    • 1 LeetCode 110.平衡二叉树
    • 2 LeetCode 257.二叉树的所有路径
    • 3 LeetCode 404.左叶子之和

1 LeetCode 110.平衡二叉树

题目链接:https://leetcode.cn/problems/balanced-binary-tree/

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

img

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

示例 3:

输入:root = []
输出:true

提示:

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

作为408选手,我想说本题也是408未来可能会涉及的题目,因此我们也必须注意一下,对于平衡二叉树的定义想必大家并不陌生(对于一棵二叉树,如果任何一个节点的左子树和右子树高度之差的绝对值不超过1,则这是一棵平衡二叉树,并且规定空平衡二叉树的高度为0,且空二叉树也是平衡的),知道平衡二叉树的定义之后,我们就很清楚我们需要分别求出节点的左子树和右子树的高度,然后求其差的绝对值是否超过1来判断,如果满足,则返回给上一层节点,以此类推,如果不满足就可以直接返回不是平衡二叉树,很明显我们需要使用后序遍历的方法来解决这道题目。

(1)Python版本代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        def checkBalance(node): 
            if not node:    # 空平衡二叉树
                return 0    
            left_height = checkBalance(node.left)   # 左子树高度
            right_height = checkBalance(node.right)     # 右子树高度
            if left_height == -1 or right_height == -1 or abs(left_height - right_height) > 1:  # 不符合平衡二叉树定义
                return -1   # -1 代表不平衡
            return max(left_height, right_height) + 1      # 返回最大高度

        return checkBalance(root) != -1

checkBalance函数用于递归地检查每个节点,如果遇到任何不平衡的子树,它会立即返回-1,这样一旦发现不平衡,递归就会提前终止,并通过连锁反应快速传递不平衡的状态回到根节点,如果树是平衡的,checkBalance会返回树的实际高度,而不是-1,因此最终的isBalanced调用检查checkBalance(root)的返回值是否不等于-1来确定整棵树是否平衡。

(2)C++版本代码

#include <iostream>
#include <algorithm>

class TreeNode {
public:
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    bool isBalanced(TreeNode* root) {
        return checkBalance(root) != -1;
    }

private:
    int checkBalance(TreeNode* node) {
        if (!node) { // 空树是平衡的
            return 0;
        }
        int leftHeight = checkBalance(node->left);
        if (leftHeight == -1) { // 左子树不平衡
            return -1;
        }
        int rightHeight = checkBalance(node->right);
        if (rightHeight == -1) { // 右子树不平衡
            return -1;
        }
        if (abs(leftHeight - rightHeight) > 1) { // 当前节点不平衡
            return -1;
        }
        return std::max(leftHeight, rightHeight) + 1; // 返回当前节点为根的树的高度
    }
};

2 LeetCode 257.二叉树的所有路径

题目链接:https://www.heywhale.com/home/activity/recent

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

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

示例 1:

img

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

示例 2:

输入:root = [1]
输出:["1"]

提示:

  • 树中节点的数目在范围 [1, 100]
  • -100 <= Node.val <= 100

本题需要涉及收集递归过程中的路径,因此会涉及到回溯,我们从根节点开始,每次遍历到一个节点时,都会检查该节点是否是叶子节点(即没有子节点),如果是叶子节点,就将从根节点到该叶子节点的路径添加到结果列表中,遍历过程中,通过字符串拼接的方式构建路径,递归的过程保证了能够访问到树的每一个节点,从而找出所有可能的路径。

(1)Python版本代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        result = []    # 用于存储所有路径的结果列表
        if not root:    # 如果根节点为空,则直接返回空的结果列表
            return result
        def dfs(node, path):    # 定义深度优先搜索函数,node为当前访问的节点,path为从根节点到当前节点的路径
            if not node.left and not node.right:    # 如果当前节点是叶子节点,将路径添加到结果列表中
                result.append(path)
            if node.left:   # 如果存在左子节点,递归调用dfs函数,路径加上"->"和左子节点的值
                dfs(node.left, path + "->" + str(node.left.val))
            if node.right:  # 如果存在右子节点,递归调用dfs函数,路径加上"->"和右子节点的值
                dfs(node.right, path + "->" + str(node.right.val))
        dfs(root, str(root.val))    # 从根节点开始递归搜索,初始路径为根节点的值
        return result   # 返回所有从根节点到叶子节点的路径

(2)C++版本代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 
#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result; // 用于存储所有路径的结果列表
        if (!root) return result; // 如果根节点为空,则直接返回空的结果列表
        
        // 定义深度优先搜索函数,node为当前访问的节点,path为从根节点到当前节点的路径
        auto dfs = [&](TreeNode* node, string path) {
            if (!node->left && !node->right) { // 如果当前节点是叶子节点,将路径添加到结果列表中
                result.push_back(path);
            }
            if (node->left) { // 如果存在左子节点,递归调用dfs函数,路径加上"->"和左子节点的值
                dfs(node->left, path + "->" + to_string(node->left->val));
            }
            if (node->right) { // 如果存在右子节点,递归调用dfs函数,路径加上"->"和右子节点的值
                dfs(node->right, path + "->" + to_string(node->right->val));
            }
        };
        
        dfs(root, to_string(root->val)); // 从根节点开始递归搜索,初始路径为根节点的值
        return result; // 返回所有从根节点到叶子节点的路径
    }
};

3 LeetCode 404.左叶子之和

题目链接:https://leetcode.cn/problems/sum-of-left-leaves/description/

给定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

img

输入: root = [3,9,20,null,null,15,7] 
输出: 24 
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

示例 2:

输入: root = [1]
输出: 0

提示:

  • 节点数在 [1, 1000] 范围内
  • -1000 <= Node.val <= 1000

这道题目力扣上面是没有详细介绍什么是左叶子,但是根据题目我们也不难看出,左叶子的定义就是某节点的左孩子存在,且其左孩子为叶子节点,那么此节点的左孩子就是左叶子。

需要注意的是,我们不能从当前节点来判断它是不是左叶子,因为左叶子本身也是叶子节点,但不能保证他是其父节点的左孩子,因此我们就需要从其父节点进行判断,判断的依据也就当左孩子的定义,我们需要用后序遍历的来进行遍历判断。

接下来我们按照卡哥的递归三部曲开始分析。

  • 确定递归函数的参数和返回值:这个很简单,我们只需要传入根节点,返回值就是数值和。
  • 确定终止条件:如果遍历到空节点,那左叶子值一定为0,我们还需要注意的是,如果当前节点不为空,但是其左右孩子不存在,我们也需要返回左叶子值为0.
  • 确定单层递归的逻辑:那就是按照左叶子的定义写即可,那就是当遍历到左叶子时就记数,然后不断递归求左子树的左叶子之和和右子树左叶子之和,最后相加。

现在我们开始写代码复现我们的思路来证明它是正确的。

(1)Python版本代码

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        if not root or (not root.left and not root.right):
            return 0
        leftNums = self.sumOfLeftLeaves(root.left)
        if root.left and not root.left.left and not root.left.right:
            leftNums += root.left.val
        rightNums = self.sumOfLeftLeaves(root.right)
        return leftNums + rightNums

(2)C++版本代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
 
class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (!root || (!root->left && !root->right)) {
            return 0;
        }
        int leftNums = sumOfLeftLeaves(root->left);
        if (root->left && !root->left->left && !root->left->right) {
            leftNums += root->left->val;
        }
        int rightNums = sumOfLeftLeaves(root->right);
        return leftNums + rightNums;
    }
};

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

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

相关文章

浅析一款非驱动考试网关程序(一)

前言 监考程序需要对网络流量进行过滤&#xff0c;不允许除了考试网站以外的其他网站的访问。其实就是实现了一个小型的网关程序&#xff0c;一般地有驱动实现和非驱动实现两种方式。本文只针对一款简易的非驱动实现的监考程序进行分析。 注意&#xff1a;本文通过对某考试监…

第十篇【传奇开心果系列】Python的OpenCV技术点案例示例:图像分割

传奇开心果短博文系列 系列短博文目录Python的OpenCV技术点案例示例系列短博文目录一、前言二、OpenCV图像分割介绍三、OpenCV分割算法示例代码四、归纳总结系列短博文目录 Python的OpenCV技术点案例示例系列 短博文目录 一、前言 OpenCV是一个广泛应用于计算机视觉和图像处…

2023年09月CCF-GESP编程能力等级认证Python编程五级真题解析

Python等级认证GESP(1~6级)全部真题・点这里 一、单选题(共15题,共30分) 第1题 近年来,线上授课变得普遍,很多有助于改善教学效果的设备也逐渐流行,其中包括比较常用的手写板,那么它属于哪类设备?( ) A:输入 B:输出 C:控制 D:记录 答案:A 第2题 以下关于…

计算机服务器中了mkp勒索病毒如何解密,mkp勒索病毒解密流程

随着网络技术的不断发展与应用&#xff0c;越来越多的企业走向数字化办公模式&#xff0c;计算机极大地方便了企业的正常生产运营&#xff0c;但网络威胁的手段也不断增加。近期&#xff0c;云天数据恢复接到很多企业的求助&#xff0c;企业的计算机服务器遭到了mkp勒索病毒攻击…

Qt 常见容器类用法(一)

目录 QMap类 QHash类 QVector类 QMap类 QMap<key,T>提供一个从类型为Key的键到类型为T的值的映射。通常&#xff0c;QMap存储的数据形式是一个键对应一个值&#xff0c;并且按照键Key的次序存储数据。为了能够支持一键多值的情况&#xff0c;QMap提供QMap<key,T&g…

相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

MPLS——多协议标签交换

目录 1 多协议标签交换 MPLS 1.1 MPLS 的工作原理 1.1.1 MPLS 工作特点 1.1.2 MPLS 协议的基本原理 1.1.3 MPLS 的基本工作过程 1.2 转发等价类 FEC 1.2.1 FEC 用于负载平衡 1.3 MPLS 首部的位置与格式 1.3.1 MPLS 首部的位置 1.3.2 MPLS 首部的格式 1.4 新一代的…

Jmeter 示例,格式为001-100,按顺序生成三位数的函数

1.先添加一个循环控制器&#xff0c;每次执行生成一个数, 2.添加一个beanshell Sample,编写代码,把按00X这个格式的数字&#xff0c;赋值给一个变量LoopCount // 从JMeter变量中获取当前的计数器值 String loopCountStr vars.get("LoopCount"); int loopCount (lo…

1896_Linux中free命令小结

1896_Linux中free命令小结 全部学习汇总&#xff1a; little_bits_of_linux: 一星半点的Linux经验 (gitee.com) 查看Linux中存储的使用情况&#xff0c;我经常使用htop&#xff0c;毕竟这个命令提供的信息是十分直观的。我现在常用的一个小主机其实是我的树莓派3B&#xff0c;虽…

ETL是什么,有哪些ETL工具?就业前景如何?

ETL是什么 ETL&#xff08;Extract-Transform-Load&#xff09;&#xff0c;用来描述将数据从来源端经过抽取(extract)、转换(transform)、加载(load)至目标端的过程。ETL一词较常用在数据仓库&#xff0c;但其对象并不限于数据仓库。它可以自动化数据处理过程&#xff0c;减少…

C#向数组指定索引位置插入新的元素值:自定义插入方法 vs List<T>.Add(T) 方法

目录 一、使用的方法 1.自定义插入方法 2.使用List.Add(T) 方法 二、实例 1.示例1&#xff1a;List.Add(T) 方法 2.示例&#xff1a;自定义插入方法 一、使用的方法 1.自定义插入方法 首先需要定义一个一维数组&#xff0c;然后修改数组的长度(这里使用Length属性获取…

正点原子--STM32基本定时器学习笔记(1)

这部分是笔者对基本定时器的理论知识进行学习与总结&#xff01;主要记录学习过程中遇到的重难点&#xff0c;其他一些基础点就一笔带过了&#xff01; 1. 定时器概述 1.1 软件定时原理 使用纯软件&#xff08;CPU死等&#xff09;的方式实现定时&#xff08;延时&#xff0…

C++ 动态规划 状态压缩DP 蒙德里安的梦想

求把 NM 的棋盘分割成若干个 12 的长方形&#xff0c;有多少种方案。 例如当 N2&#xff0c;M4 时&#xff0c;共有 5 种方案。当 N2&#xff0c;M3 时&#xff0c;共有 3 种方案。 如下图所示&#xff1a; 2411_1.jpg 输入格式 输入包含多组测试用例。 每组测试用例占一行…

A64指令集架构之PCS过程调用标准

Arm架构对通用寄存器的使用几乎没有限制。简而言之&#xff0c;整数寄存器和浮点寄存器都是通用寄存器。然而&#xff0c;如果你希望你的代码与他人编写的代码互动&#xff0c;或者与编译器生成的代码互动&#xff0c;那么你需要就寄存器的使用达成一致的规则。对于Arm架构&…

Chronos靶机渗透

Chronos靶机 一.信息收集1.靶机IP地址确认2.目录扫描3.常见漏洞扫描5.web网站探测1.网页2.源代码 二.网站渗透1.命令执行2.抓包---burp suite3.反弹shell 三.提权1.node.js原核污染第一个flag 2.sudo提权第二个flag 一.信息收集 1.靶机IP地址确认 ┌──(root㉿kali)-[/] └─…

【Linux系统化学习】文件描述符fd

目录 基础IO预备知识 C语言文件接口 "w"的方式打开&#xff0c;fputs写入 以"a"的方式打开&#xff0c;fputs写入 使用位图传参 系统调用操作文件 open的使用 第一种形式 第二种形式 write() 文件描述符 文件描述符和进程的关系 默认的三个IO流…

JAVASE进阶:高级写法——方法引用(Mybatis-Plus必学前置知识)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;JAVASE进阶&#xff1a;一文精通Stream流函数式编程 &#x1f4da;订阅专栏&#xff1a;JAVASE进阶 希望文章对你们有所帮助 相信…

SpringCloud--Eureka注册中心服务搭建注册以及服务发现

注意springboot以及springcloud版本&#xff0c;可能有莫名其妙的错误&#xff0c;这里使用的是springboot-2.6.13&#xff0c;springcloud-2021.0.5 一&#xff0c;Eureka-Server搭建&#xff1a; 1.创建项目&#xff1a;引入依赖 <dependency><groupId>org.sp…

MyBatis 分页插件 PageHelper-Dazer007

文章目录 MyBatis 分页插件 PageHelper-Dazer0071、使用方式1.1 原始PageHelper1.2 ruoyi框架封装PageHelper1.3 MyBaits-Plus自带分页&#xff0c;无需PageHeler 2、作用原理3、数据方言实现3.1、MySqlDialect3.2、OracleDialect3.3、SqlServer2012Dialect 3、数据方言实现 My…

【Spring】Spring事务和事务传播机制

文章目录 什么是事务事务的操作Spring 中事务的实现Spring编程式事务Spring 声明式事务 TransactionalTransactional作用Transactional 详解rollbackFor事务隔离级别Spring 事务隔离级别Spring 事务传播机制 什么是事务 事务&#xff08;Transaction&#xff09;是一个程序中一…