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

leetcode地址:二叉搜索子树的最大键值和
给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。
二叉搜索树的定义如下:
任意节点的左子树中的键值都 小于 此节点的键值。
任意节点的右子树中的键值都 大于 此节点的键值。
任意节点的左子树和右子树都是二叉搜索树。

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

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

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

输入:root = [-4,-2,-5]
输出:0
解释:所有节点键值都为负数,和最大的二叉搜索树为空。
示例 4:

输入:root = [2,1,3]
输出:6
示例 5:

输入:root = [5,4,8,3,null,6,3]
输出:7

提示:

每棵树有 1 到 40000 个节点。
每个节点的键值在 [-4 * 10^4 , 4 * 10^4] 之间。

实现思路

要解决这个问题,我们需要计算二叉树中每一个子树是否是二叉搜索树(BST),并计算所有BST子树的键值和,最终返回这些BST子树中的最大键值和。

我们可以使用递归的方法来解决这个问题。递归地遍历树中的每一个节点,同时计算子树的信息,包括:

  1. 是否是BST
  2. 子树的键值和
  3. 子树的最小键值
  4. 子树的最大键值

具体步骤如下:

  1. 定义一个辅助函数 dfs(node),它返回四个值:
    is_bst:当前子树是否为BST
    subtree_sum:当前子树的键值和
    min_val:当前子树的最小键值
    max_val:当前子树的最大键值 递归计算左子树和右子树的信息。
  2. 根据左子树和右子树的信息,以及当前节点的值,判断当前子树是否为BST。
  3. 如果是BST,则计算当前子树的键值和、最小键值和最大键值。
  4. 更新最大BST键值和的结果。
  5. 返回当前子树的信息。

代码详解

 假设有以下二叉树:1/ \4   3/   / \2   2   5

首先定义树节点类 TreeNode,用于构建二叉树:

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = right

TreeNode 类有三个属性:

val:节点的值。
left:左子树。
right:右子树。

接下来是主函数 max_sum_BST,它计算二叉树中任意二叉搜索子树的最大键值和:

def max_sum_BST(root):def dfs(node):if not node:# 空节点被认为是BST,其和为0,最小值为正无穷大,最大值为负无穷大return True, 0, float('inf'), float('-inf')

dfs 辅助函数
dfs 函数接收一个节点 node 作为参数,返回四个值:

is_bst:布尔值,表示当前子树是否为BST。
subtree_sum:当前子树的键值和。
min_val:当前子树的最小键值。
max_val:当前子树的最大键值。

若 node 为 None,即为空节点,则返回:

True:空节点被认为是BST。
0:空节点的键值和为0。
float('inf'):空节点的最小键值为正无穷大。
float('-inf'):空节点的最大键值为负无穷大。
  left_is_bst, left_sum, left_min, left_max = dfs(node.left)right_is_bst, right_sum, right_min, right_max = dfs(node.right)

递归计算左子树和右子树的信息,包括是否为BST、键值和、最小键值和最大键值。

# 检查当前节点为根的子树是否为BST
if left_is_bst and right_is_bst and left_max < node.val < right_min:subtree_sum = left_sum + node.val + right_summax_sum[0] = max(max_sum[0], subtree_sum)return True, subtree_sum, min(left_min, node.val), max(right_max, node.val)
else:# 当前子树不是BST,返回假return False, 0, float('-inf'), float('inf')

检查当前节点为根的子树是否为BST,条件是:

左子树是BST。
右子树是BST。
当前节点的值大于左子树的最大值且小于右子树的最小值。

若满足上述条件,则当前子树是BST:

计算当前子树的键值和 subtree_sum。
更新全局最大BST键值和 max_sum[0]。
返回 True、subtree_sum、当前子树的最小键值和最大键值。
否则,当前子树不是BST,返回 False、键值和0、最小键值为负无穷大、最大键值为正无穷大。
   max_sum = [0]dfs(root)return max_sum[0]

在 max_sum_BST 函数中:
max_sum 是一个列表,存储最大BST键值和。使用列表是为了在 dfs 函数中能够修改其值。
调用 dfs(root),开始递归遍历树。
返回 max_sum[0],即最大BST键值和。

class TreeNode:def __init__(self, val=0, left=None, right=None):self.val = valself.left = leftself.right = rightdef max_sum_BST(root):def dfs(node):if not node:# 空节点被认为是BST,其和为0,最小值为正无穷大,最大值为负无穷大return True, 0, float('inf'), float('-inf')left_is_bst, left_sum, left_min, left_max = dfs(node.left)right_is_bst, right_sum, right_min, right_max = dfs(node.right)# 检查当前节点为根的子树是否为BSTif left_is_bst and right_is_bst and left_max < node.val < right_min:subtree_sum = left_sum + node.val + right_summax_sum[0] = max(max_sum[0], subtree_sum)return True, subtree_sum, min(left_min, node.val), max(right_max, node.val)else:# 当前子树不是BST,返回假return False, 0, float('-inf'), float('inf')max_sum = [0]dfs(root)return max_sum[0]# 测试示例
if __name__ == "__main__":# 创建测试二叉树#        1#       / \#      4   3#     /   / \#    2   2   5root = TreeNode(1)root.left = TreeNode(4)root.right = TreeNode(3)root.left.left = TreeNode(2)root.right.left = TreeNode(2)root.right.right = TreeNode(5)result = max_sum_BST(root)print(f"最大BST子树的键值和: {result}")  # 应该输出6

GO语言实现

package mainimport ("fmt""math"
)// TreeNode 定义二叉树节点
type TreeNode struct {Val   intLeft  *TreeNodeRight *TreeNode
}// maxSumBST 函数返回二叉树中任意二叉搜索子树的最大键值和
func maxSumBST(root *TreeNode) int {maxSum := 0// dfs 辅助函数返回四个值:是否是BST、子树键值和、最小键值、最大键值var dfs func(node *TreeNode) (bool, int, int, int)dfs = func(node *TreeNode) (bool, int, int, int) {if node == nil {// 空节点被认为是BST,其和为0,最小值为正无穷大,最大值为负无穷大return true, 0, math.MaxInt64, math.MinInt64}leftIsBST, leftSum, leftMin, leftMax := dfs(node.Left)rightIsBST, rightSum, rightMin, rightMax := dfs(node.Right)// 检查当前节点为根的子树是否为BSTif leftIsBST && rightIsBST && leftMax < node.Val && node.Val < rightMin {subtreeSum := leftSum + node.Val + rightSumif subtreeSum > maxSum {maxSum = subtreeSum}return true, subtreeSum, min(leftMin, node.Val), max(rightMax, node.Val)}// 当前子树不是BST,返回假return false, 0, math.MinInt64, math.MaxInt64}dfs(root)return maxSum
}// 辅助函数:返回两个整数中的较小值
func min(a, b int) int {if a < b {return a}return b
}// 辅助函数:返回两个整数中的较大值
func max(a, b int) int {if a > b {return a}return b
}// 测试示例
func main() {// 创建测试二叉树//        1//       / \//      4   3//     /   / \//    2   2   5root := &TreeNode{Val: 1}root.Left = &TreeNode{Val: 4}root.Right = &TreeNode{Val: 3}root.Left.Left = &TreeNode{Val: 2}root.Right.Left = &TreeNode{Val: 2}root.Right.Right = &TreeNode{Val: 5}result := maxSumBST(root)fmt.Printf("最大BST子树的键值和: %d\n", result) // 应该输出6
}

kotlin实现

// 定义二叉树节点类
class TreeNode(var `val`: Int) {var left: TreeNode? = nullvar right: TreeNode? = null
}// maxSumBST 函数返回二叉树中任意二叉搜索子树的最大键值和
fun maxSumBST(root: TreeNode?): Int {var maxSum = 0// dfs 辅助函数返回四个值:是否是BST、子树键值和、最小键值、最大键值fun dfs(node: TreeNode?): Quad<Boolean, Int, Int, Int> {if (node == null) {// 空节点被认为是BST,其和为0,最小值为正无穷大,最大值为负无穷大return Quad(true, 0, Int.MAX_VALUE, Int.MIN_VALUE)}val (leftIsBST, leftSum, leftMin, leftMax) = dfs(node.left)val (rightIsBST, rightSum, rightMin, rightMax) = dfs(node.right)// 检查当前节点为根的子树是否为BSTif (leftIsBST && rightIsBST && leftMax < node.`val` && node.`val` < rightMin) {val subtreeSum = leftSum + node.`val` + rightSumif (subtreeSum > maxSum) {maxSum = subtreeSum}return Quad(true, subtreeSum, minOf(leftMin, node.`val`), maxOf(rightMax, node.`val`))}// 当前子树不是BST,返回假return Quad(false, 0, Int.MIN_VALUE, Int.MAX_VALUE)}dfs(root)return maxSum
}// Quad 数据类,用于返回四个值
data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)// 测试示例
fun main() {// 创建测试二叉树//        1//       / \//      4   3//     /   / \//    2   2   5val root = TreeNode(1)root.left = TreeNode(4)root.right = TreeNode(3)root.left?.left = TreeNode(2)root.right?.left = TreeNode(2)root.right?.right = TreeNode(5)val result = maxSumBST(root)println("最大BST子树的键值和: $result") // 应该输出6
}

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

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

相关文章

IOC、DI<4> Unity

IOC&#xff08;&#xff09;&#xff1a;控制反转&#xff0c;把程序上层对下层的依赖&#xff0c;转移到第三方的容器来装配 是程序设计的目标&#xff0c;实现方式包含了依赖注入和依赖查找&#xff08;.net里面只有依赖注入&#xff09; DI&#xff1a;依赖注入&#xff0c…

基于jeecgboot-vue3的Flowable流程-集成仿钉钉流程(一)一些样式的调整使用

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、比如下面的发起人双击后出现的界面不正常&#xff0c; 看它的样式主要是这个里面的margin-left应该太小了&#xff0c; [data-v-45b533d5] .el-tabs__content { margin-top: 50px;mar…

7.1作业6

uart4.h #ifndef __UART4_H__ #define __UART4_H__ #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_uart.h" //rcc/gpio/uart4初始化 void hal_uart4_init(); //发送一个字符 void hal_put_char(const char s…

香橙派编译linux内核支持ebpf和虚拟WIFI

前言 上一篇文章香橙派5plus上跑云手机方案一 redroid(带硬件加速)中说了怎么运行redroid&#xff0c;这篇补一下怎么修改参数编译内核。 补充 上篇文章有个内容需要补充一下&#xff1a;更新完内核需要用下面的命令防止内核被apt更新&#xff0c;不然后面使用apt update又回…

浅析C++引用

浅析C引用"&" ​ C中引入了一个新的语言特性——引用(&)&#xff0c;它表示某一对象的别名&#xff0c;对象与该对象的引用都是指向统一地址。那么我们就来看看关于引用的一些知识点吧&#x1f9d0; 特性 引用在定义时必须初始化一个变量可以有多个引用引…

【Python】一文向您详细介绍 np.inner()

【Python】一文向您详细介绍 np.inner() 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&#xff0c;曾…

JavaWeb系列二十二: 线程数据共享和安全(ThreadLocal)

韩顺平-线程数据共享和安全ThreadLocal 什么是ThreadLocal?ThreadLocal环境搭建ThreadLocal快速入门ThreadLocal源码阅读threadLocal.set()源码threadLocal.get()源码 什么是ThreadLocal? ThreadLocal的作用: 可以实现在同一个线程数据共享, 从而解决多线程数据安全问题.Thr…

小阿轩yx-Haproxy搭建Web群集

小阿轩yx-Haproxy搭建Web群集 Haproxy 简介 提供高可用性 能做出标准的负载均衡 支持虚拟主机 具备健康检查能力 能用于各式各样的代理 轻量级代理环境 解决方案优势 免费 快速 可靠 特性 特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或…

前端面试题24(css3)

下面是一些常见的 CSS3 面试题&#xff0c;这些问题可以帮助你评估应聘者对 CSS3 的掌握程度&#xff1a; 1. 解释 CSS3 中的动画关键帧&#xff08;keyframes&#xff09;和它们是如何工作的&#xff1f; 回答要点&#xff1a;keyframes 规则用于创建动画&#xff0c;它可以…

后端之路——文件本地上传

一、基础原理 文件上传是一个很基础的知识点&#xff0c;尤其是本地上传&#xff0c;在现实开发基本都是云上传&#xff0c;但是作为一个基础要简单了解一下 首先前端我就不多讲解了&#xff0c;网页开发里用<form>表单可以上传文件&#xff0c;只需要加上这三属性&…

pytest系列——pytest_runtest_makereport钩子函数获取测试用例执行结果

前言 pytest测试框架提供的很多钩子函数方便我们对测试框架进行二次开发&#xff0c;可以根据自己的需求进行改造。 例如&#xff1a;钩子方法&#xff1a;pytest_runtest_makereport &#xff0c;可以更清晰的了解测试用例的执行过程&#xff0c;并获取到每个测试用例的执行…

(译文)IRIG-B对时编码快速入门

原文 PDF&#xff1a;https://ww1.microchip.com/downloads/aemDocuments/documents/FTD/tekron/tekronwhitepapers/221223-A-guide-to-IRIG-B.pdf IRIG-B3 概论 Inter-Range Instrument Group 时间码&#xff08;简称IRIG&#xff09;是一系列标准时间码格式。用于将时间信…

使用Cloudflare免费开启全站https配置SSL证书

HTTPS 我的服务器和域名是在华为云&#xff0c;华为云SSL证书巨贵&#xff0c;通过Cloudflare可以将自己的网站免费设置成https。 Cloudflare注册 访问Cloudflare, 注册账号。 添加站点 添加你自己的站点&#xff0c;选择免费的套餐。 添加DNS 添加你的域名、子域名、…

PCB阻抗控制为何如此重要?

或许你在各个厂商打PCB板的时候&#xff0c;会遇到询问你是否需要阻抗的的下单需求&#xff1f; 在当今的应用中&#xff0c;设计通常变得越来越快&#xff0c;控制布局参数比以往任何时候都更加重要。 在PCB设计和生产过程中&#xff0c;有几种方法可以进行阻抗控制。最常见的…

轻松转换!两款AI工具让word秒变ppt!

想把Word文档一键生成PPT&#xff0c;过去有一个很常见的做法&#xff1a;先在Word文档中设置标题样式&#xff0c;通过标题样式来分隔每一部分&#xff0c;之后导出为PPT&#xff0c;就能得到一份PPT的雏形&#xff0c;但这种方法无法对PPT自动进行美化&#xff0c;即得到的只…

ZGC在三色指针中的应用

ZGC基于颜色指针的并发处理算法 ZGC初始化之后&#xff0c;整个内存空间的地址视图被设置为Remapped&#xff0c;当进入标记阶段时的视图转变为Marked0&#xff08;也称为M0&#xff09;或者Marked1&#xff08;也称为M1&#xff09;&#xff0c;从标记阶段结束进入转移阶段时…

计算机学生在大学四年应是以数据结构和算法为重还是技术为重?

我给你说点比较实在的吧&#xff0c;不管你是不是计算机专业科班出身的大学生&#xff0c;不管你在不在本科大学&#xff0c;不管你的出身和背景如何&#xff0c;想要走上计算机工作岗位&#xff0c;那必须得有拿得出手的一技之长&#xff0c;这个行业是靠技术吃饭的。 刚好我有…

Kotlin算法:把一个整数向上取值为最接近的2的幂指数值

Kotlin算法&#xff1a;把一个整数向上取值为最接近的2的幂指数值 import kotlin.math.ln import kotlin.math.powfun main(args: Array<String>) {val number intArrayOf(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18)number.forEach {println("$…

一.1 信息就是位+上下文

hello程序的生命周期是从一个源程序&#xff08;或者说源文件&#xff09;开始的&#xff0c;即程序员通过编辑器创建并保存的文本文件&#xff0c;文件名是hello.c。源程序实际上就是一个由0和1组成的位&#xff08;又称为比特&#xff09;序列&#xff0c;8个位被组织成一组&…

python读取指定文件夹下的图片(glob获取)

python读取指定文件夹下的图片&#xff08;glob获取&#xff09; 定义traverse_images函数&#xff0c;仅需要改变下根路径即可 glob是python中用来查找符合特定规则的文件路径名的函数 import os from glob import globdef traverse_images (folder_path):image_formats …