【leetcode】1373. 二叉搜索子树的最大键值和

news2024/11/15 14:08:52

二叉搜索子树的最大键值和

  • 问题描述
  • 问题简单分析
  • 提交之旅
    • 第一次提交-失败
    • 第二次提交-失败
    • 第三次提交-成功

问题描述

二叉搜索子树的最大键值和
给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。
二叉搜索树的定义如下:

  • 任意节点的左子树中的键值都 小于 此节点的键值。
  • 任意节点的右子树中的键值都 大于 此节点的键值。
  • 任意节点的左子树和右子树都是二叉搜索树。
    示例 1:

leetcode示例图
输入:root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]
输出:20
解释:键值为 3 的子树是和最大的二叉搜索树。

问题简单分析

对于树的处理一般都采用递归的方式,再配以某种遍历(前序、中序、后序)方式。对于该问题也是类似的处理方式。
本问题本质上从一颗二叉树中查找节点之和最大二叉搜索树

判断某个节点的子树是否是二叉搜索树,需要先检查该节点的左右子树是否是二叉搜索树,再判断该节点是否是二叉搜索树,因此这里使用的是后序遍历的方式。当左子树或右子树任意一个不满足时,该子树的祖先节点都将不是二叉搜索树。

父节点需要能够区分左右子树是否是二叉搜索树。

基于以上考虑,就有了第一次提交。

提交之旅

第一次提交-失败

二叉搜索子树的区分:当返回值小于0,表示不是二叉搜索树

class Solution {
public:
    int maxSumBST(TreeNode* root) {
        int maxSum = 0;
        maxSumBST(root, maxSum);
        return maxSum;
    }

    int maxSumBST(TreeNode* root, int& maxSum) {
    	//如果是空节点,则直接返回0,避免左右子树这里还要加个是否为空的处理逻辑
        if(root == nullptr){
            return 0;
        }
        int leftSum = maxSumBST(root->left, maxSum);
        int rightSum = maxSumBST(root->right, maxSum);
        //后序处理逻辑
        //当左右子树任意个小于0,则返回-1,表示不是二叉搜索树
        if(leftSum < 0 || rightSum < 0){
            return -1;
        }
        //左节点不小于父节点,则说明不是二叉搜索树,返回-1 ---- 这里存在问题
        if(root->left != nullptr && root->val <= root->left->val){
            return -1;
        }
        //右节点不大于父节点,则说明不是二叉搜索树,返回-1 ---- 这里存在问题
        if(root->right != nullptr && root->val >= root->right->val){
            return -1;
        }
        //统计二叉搜索树的节点之和
        int sum = root->val + leftSum + rightSum;
        if(maxSum < sum){
            maxSum = sum;
        }
        return sum;
    }

};

提交后就失败了,失败用例:[1,null,10,-5,20],期望是25,而实际返回20。原因如下:
节点10的左子节点是一个叶子节点,但是由于其值为-5(小于0),被误判为非二叉搜索树,导致[10,-5,20] 这颗子树也被误判为非二叉搜索树,因此最终返回20。

因此必须想其他方案来区分是否是二叉搜索树,因此就有了第二次提交。

第二次提交-失败

二叉搜索子树的区分:通过tuple(是否是二叉搜索树,树节点之和,最小节点)中专门字段来区分,当为true,则表示是二叉搜索树

class Solution {
public:
    int maxSumBST(TreeNode* root) {
        int maxSum = 0;
        maxSumBST(root, maxSum);
        return maxSum;
    }

    tuple<bool,int,TreeNode*> maxSumBST(TreeNode* root, int& maxSum) {
        if(root == nullptr){
            return make_tuple(true, 0, nullptr);
        }
        tuple<bool,int,TreeNode*> left = maxSumBST(root->left, maxSum);
        tuple<bool,int,TreeNode*> right = maxSumBST(root->right, maxSum);
        if(!std::get<0>(left) || !std::get<0>(right)){
            return make_tuple(false, 0, nullptr);
        }
        //左子树的最小节点不小于父节点,则说明不是二叉搜索树,返回-1 ---- 这里存在问题
        if(std::get<2>(left) && root->val <= std::get<2>(left)->val) {
            return make_tuple(false, 0, nullptr);
        }
        //右子树的最小节点不大于父节点,则说明不是二叉搜索树,返回-1
        if(std::get<2>(right) && root->val >= std::get<2>(right)->val) {
            return make_tuple(false, 0, nullptr);
        }
        int sum = root->val + std::get<1>(left) + std::get<1>(right);
        if(maxSum < sum){
            maxSum = sum;
        }
        return make_tuple(true, sum, (root-> left ? root->left : root));
    }

};

为啥tuple中会有 最小节点?这是因为用例[1,null,10,-5,20]期望是25,而实际返回26,这是因为原来的实现是通过判断节点跟其左右节点的关系来判断是否是二叉搜索树,这就导致误将[1,null,10,-5,20]也当作合法的二叉搜索树。
[10,-5,20]是合法的二叉搜索树,[1,null,10]也是合法的二叉搜索树,但是[1,null,10,-5,20]树中-5在1的右子树上,但小于1,所以这棵树不是合法的二叉搜索树。

既然右子树的最小节点不大于父节点,那么应该是左子树的最大节点不小于父节点,而不是左子树的最小节点不小于父节点?这是因为测试时不小心点了提交!

第三次提交-成功

二叉搜索树判定:父节点需要大于左子树的最大节点,小于右子树的最小节点。

class Solution {
public:
    int maxSumBST(TreeNode* root) {
        int maxSum = 0;
        maxSumBST(root, maxSum);
        return maxSum;
    }

	//返回:是否是二叉搜索树,树节点之和,最小节点,最大节点
    tuple<bool,int,TreeNode*,TreeNode*> maxSumBST(TreeNode* root, int& maxSum) {
        if(root == nullptr){
            return make_tuple(true, 0, nullptr, nullptr);
        }
        tuple<bool,int,TreeNode*,TreeNode*> left = maxSumBST(root->left, maxSum);
        tuple<bool,int,TreeNode*,TreeNode*> right = maxSumBST(root->right, maxSum);
        if(!std::get<0>(left) || !std::get<0>(right)){
            return make_tuple(false, 0, nullptr, nullptr);
        }
        //根节点需要大于左子树的最大值
        if(std::get<3>(left) && root->val <= std::get<3>(left)->val) {
            return make_tuple(false, 0, nullptr, nullptr);
        }
        //根节点需要小于右子树的最小值
        if(std::get<2>(right) && root->val >= std::get<2>(right)->val) {
            return make_tuple(false, 0, nullptr, nullptr);
        }
        int sum = root->val + std::get<1>(left) + std::get<1>(right);
        if(maxSum < sum){
            maxSum = sum;
        }
        //找到该节点子树的最大最小节点
        TreeNode* min = std::get<2>(left) ? std::get<2>(left) : root;
        TreeNode* max = std::get<3>(right) ? std::get<3>(right) : root;;
        return make_tuple(true, sum, min, max);
    }

};

核心关键点:

  • 后序遍历
  • 二叉搜索树的判定:节点值大于左子树的最大值,小于右子树的最小值。

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

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

相关文章

JVM学习(六)

1. JAVA 集合 1.1. 接口继承关系和实现 集合类存放于 Java.util 包中&#xff0c;主要有 3 种&#xff1a;set(集&#xff09;、list(列表包含 Queue&#xff09;和 map(映射)。 1. Collection&#xff1a;Collection 是集合 List、Set、Queue 的最基本的接口。 2. Iterato…

Apple Safari 16.5 发布- macOS 专属浏览器 (独立安装包下载)

Apple Safari 16.5 - macOS 专属浏览器 (独立安装包下载) Safari 浏览器 16 for macOS Montery, Big Sur 请访问原文链接&#xff1a;https://sysin.org/blog/apple-safari-16/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org…

DevOps系列文章-Kubernetes实现CI与CD配置

Kubernetes实现CI与CD配置 一、基本介绍 基于 Kubernetes 实现 CI/CD 配置&#xff0c;其实和往常那些 CI/CD 配置并没有太大区别。都是通过 提交代码&#xff0c;拉取代码&#xff0c;构建代码&#xff0c;发布代码来实现的。 只不过要是通过 K8s 来实现的话&#xff0c;则是…

HNU-计算机系统-讨论课7

选题三 、我们自己来写&#xff0c;太“库”啦 ~ &#xff08; 1 &#xff09; 在 Linux 里用 C 语言进行代码设计&#xff0c;能对某一个班级、某一门 课程、某一名学生的分数进行分析&#xff0c;比如分数段、最高分、最低 分、排名、优势课程等&#xff0c;具体涉及分析…

【计算机系统基础bomb lab】CSAPP实验:Bomb Lab

CSAPP 实验&#xff1a;Bomb Lab 实验内容简述 作为实验目标的二进制炸弹 “Bomb Lab” Linux可执行程序包含了多个阶段(或关卡)&#xff0c;在每个阶段程序要求输入一-个特定字符串&#xff0c;如果输入满足程序代码所定义的要求&#xff0c;该阶段的炸弹就被拆除了&#xf…

基于Zynq的雷达10Gbps高速PCIE数据采集卡方案(二)硬件设计

3.1 引言 采集卡的硬件设计是实现采集功能的基础&#xff0c;良好的硬件设计可以使采集功能更容 易实现&#xff0c;方便软件开发。本章基于第二章的硬件设计方案来详细介绍采集卡硬件设计。 包括载卡和子卡的芯片的选型、配置和具体电路的设计。载卡和子卡的硬件设计总体 …

美联储内部分歧不断加大 妥协方案:6月“跳过”,7月再加

在周五举行的托马斯劳巴赫研究会议上&#xff0c;美联储主席鲍威尔、前主席伯南克一同出席&#xff0c;并对当前的热点政策问题发表了看法。货币政策&#xff0c;自然是备受关注的议题。 凭借研究“银行和金融危机”荣获2022年诺贝尔经济学奖的伯南克表示&#xff0c;银行业危机…

Linux文件与目录管理笔记1

鸟哥私房菜笔记 这里写目录标题 常用文件命令cd,pwd,mkdir,rmdir 执行文件的路径的变量:$PATHls,cp,rm,mv 文件内容查看指令(cat,tac,nl)可翻页查看(more,less)More(一页一页翻动)less 数据截取&#xff08;head,tail&#xff09;非纯文本文件&#xff1a;od 常用文件命令 cd…

lwIP:宏 LWIP_TCPIP_CORE_LOCKING(内核锁定)

从 lwIP-2.0.0 开始&#xff0c;在 opt.h 中多了一个宏开关 LWIP_TCPIP_CORE_LOCKING&#xff0c;默认使能。这个宏是启用内核锁定功能的。 本文探索这个宏的前世今生。 2007 年 5 月 24 日&#xff0c;Simon Goldschmid &#xff08;以下简称 西蒙 &#xff09;提交了一个任务…

DriveAct:用于自动驾驶汽车细粒度驾驶员行为识别的多模态数据集

Drive&Act&#xff1a;A Multi-modal Dataset for Fine-grained Driver Behavior Recognition in Autonomous Vehicles 摘要1. 简介2. 其它驾驶员动作数据集3. Drive&Act数据集3.1 数据采集3.2 记录的数据流传感器设置和视频流3D Body Pose3D Head PoseInterior ModelA…

接口优化技巧汇总

1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库&#xff0c;避免多次IO。 //批量入库 batchInsert();2.异步处理 异步思想&#xff1a;针对耗时比较…

短视频去水印接口 支持各短视频平台去水印 快速稳定

短视频去水印接口 支持各短视频平台去水印&#xff0c;抖音、快手、微视、西瓜等。 快速稳定 不限次 免费测试 接口开发文档 返回格式&#xff1a; JSON 请求方式&#xff1a; GET/POST 请求示例&#xff1a; 请求参数说明&#xff1a; 字段必填类型说明url是String短视…

听说你想成为一名6的飞起的黑客,这些资料怎么能少

重点提醒&#xff1a;本项目工具来源于互联网&#xff0c;是否含带木马及后门请自行甄别&#xff01;&#xff01;Hvv来即&#xff0c;请大家提高警惕&#xff01;&#xff01;&#xff01; 受限于篇幅原因&#xff0c;无法全部展示&#xff0c;如果你需要的话&#xff0c;可以…

【正点原子STM32连载】 第十章 STM32CubeMX简介 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十章…

教你精通Java语法之第十四章、枚举

目录 一、背景及定义 二、使用 2.1switch语句 2.2常用方法 三、枚举优点缺点 四、枚举和反射 4.1枚举是否可以通过反射&#xff0c;拿到实例对象呢&#xff1f; 五、总结 六、面试问题 一、背景及定义 枚举是在JDK1.5以后引入的。主要用途是&#xff1a;将一组常量组织…

触发器章节小结

触发器&#xff08;Flip Flop&#xff09; 4.1 SR锁存器&#xff08;Set-Reset Latch&#xff09; 4.1.1 或非门构成的SR锁存器 SD称为置位端或置1输入端&#xff1b; RD称为复位端或置0输入端。 当SD 1、RD 0时,Q1、Q’0。在SD 1信号消失以后&#xff08;即SD 回到0)&#…

AI绘画-Midjourney基础1-突破想象的界限:掌握文本引导的图像生成技巧

Midjourney是一款 AI 绘画工具&#xff0c;可以根据你的提示&#xff08;本文中称为 prompt&#xff09;创作出各种图像。你只需要在Discord上和一个机器人聊天&#xff0c;就可以用简单的命令来控制它。目前已不支持免费试用&#xff0c;可以选择付费计划来获得更多功能和优势…

viet构建项目及<script setup>的用法

vite构建项目 官方文档&#xff1a;https://v3.cn.vuejs.org/guide/installation.html#vite vite 官网&#xff1a;https://vitejs.cn 什么是 vite&#xff1f;—— 新一代前端构建工具。 优势如下&#xff1a; 开发环境中&#xff0c;无需打包操作&#xff0c;可快速的冷启动。…

操作系统易错题

操作系统易错题 假设某硬盘由5个盘片构成&#xff08;共有8个记录面&#xff09;&#xff0c;盘面有效记录区域的外直径为30cm&#xff0c;内直径为10cm&#xff0c;记录位密度为250位/mm&#xff0c;磁道密度为16道/mm&#xff0c;每磁道分16个扇区&#xff0c;每扇区512字节&…

【图像分割】卫星遥感影像道路分割:D-LinkNet算法解读

前言 因为毕设中的部分内容涉及到卫星遥感影像道路分割&#xff0c;因此去对相关算法做了一些调研。 本文所使用数据集为DeepGlobe&#xff0c;来自于CVPR2018年的一个挑战赛&#xff1a;DeepGlobe Road Extraction Challenge。 D-LinkNet为该挑战赛的冠军算法。 考虑到D-Lin…