LeetCode 第 1373 题:二叉搜索子树的最大键值和

简介: 在判断是否为 BST 的时候,可以使用后序遍历来记录 root 的左右子树是否为 BST 并且返回 root 树的最大和最小值,以及 root 的键值和。

LeetCode 第 1373 题:二叉搜索子树的最大键值和

题目 1373. 二叉搜索子树的最大键值和 的要求是,给你一颗以 root 为根的二叉树,要求返回任意二叉搜索子树的最大键值和。

首先要注意的是,给定的二叉树不一定是一颗二叉搜索树,所以我们要判断以某个节点为根节点的子树是否为二叉搜索树。

二叉搜索树的定义如下:

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

暴力法

首先用比较暴力的解法,我们可以从根节点开始,判断以当前节点为根节点的二叉树是否为二叉搜索树(BST),如果是的话就计算这棵 BST 的键值和,然后更新最大键值和。可以给出如下代码:

class Solution:
    from collections import defaultdict
    def __init__(self):
        self.maxKeySum = 0  # 记录最大的 BST 键值和
        self.hashMap = defaultdict(int)  # 用一个哈希表来记录以当前节点为根节点的子树键值和

    def keySum(self, root):
        if not root: return 0
        leftVal = self.keySum(root.left)   # 得到左子树的键值和
        rightVal = self.keySum(root.right) # 得到右子树的键值和
        self.hashMap[root] = root.val + leftVal + rightVal
        return self.hashMap[root]  # 返回当前节点为根的树的键值和

    def findMax(self, root):  # 寻找最大的 BST 键值和
        if not root: return
        # 前序遍历
        # 如果 root 为 BST 并且其键值和大于当前最大键值和,就更新值
        if self.isBST(root) and (self.hashMap[root] > self.maxKeySum):
            self.maxKeySum = self.hashMap[root]
        self.maxSumBST(root.left) 
        self.maxSumBST(root.right) 

    def isBST(self, root, minNode=None, maxNode=None): # 验证是否为 BST
        if (root == None): return True
        if (minNode and root.val <= minNode.val): return False
        if (maxNode and root.val >= maxNode.val): return False
        return self.isBST(root.left, minNode, root) and self.isBST(root.right, root, maxNode)

    def maxSumBST(self, root: Optional[TreeNode]) -> int:
        # 要判断以当前节点为根节点的树是否为二叉搜索树
        # 如果是的话更新最大键值和
        # 用前序
        self.keySum(root)  # 先创建键值和哈希表
        self.findMax(root) # 找到最大键值和
        return self.maxKeySum # 返回最大键值和

这个方法是能够对的,但是由于其时间复杂度太高,所以肯定是超时了。主要的原因在于每次调用函数 isBST(root) 的时候,都会重复遍历子节点。

后序遍历

在判断是否为 BST 的时候,可以使用后序遍历来记录 root 的左右子树是否为 BST 并且返回 root 树的最大和最小值,以及 root 的键值和。或者说,就是把上面的代码所有的函数都写成后序遍历的形式然后合并一下,得到下面的代码:

class Solution:
    from collections import defaultdict
    def __init__(self):
        self.maxKeySum = 0

    def traverse(self, root):
        if not root: return (True, float('-inf'), float('inf'), 0)
        leftIsBST, lMax, lMin, leftVal = self.traverse(root.left)
        rightIsBST, rMax, rMin, rightVal = self.traverse(root.right)
        # 后序遍历位置
        rootIsBST = leftIsBST and rightIsBST and (root.val > lMax) and (root.val < rMin)
        rootKeySum = root.val + leftVal + rightVal
        rootMax = max(lMax, rMax, root.val)
        rootMin = min(lMin, rMin, root.val)
        # 如果 root 是 BST 则更新最大键值和
        if rootIsBST:
            self.maxKeySum = max(self.maxKeySum, rootKeySum)
        # 返回 root 是否为 BST,最大值,最小值,键值和
        return (rootIsBST, rootMax, rootMin, rootKeySum)

    def maxSumBST(self, root: Optional[TreeNode]) -> int:
        # 要判断以当前节点为根节点的树是否为二叉搜索树
        # 如果是的话更新最大键值和
        self.traverse(root)
        return self.maxKeySum

提供一个判断一棵树是否为 BST 的代码框架:

def isValidBST(root):
    return isValid(root, None, None)

# 让 root 的信息能够传给子树节点
def isValid(root, minNode, maxNode):
    if (root == None): return True
    if (minNode and root.val <= minNode.val): return False
    if (maxNode and root.val >= maxNode.val): return False
    # 左子树最大的值不能超过 root 节点
    # 右子树最小的值不能超过 root 节点
    return isValid(root.left, minNode, root) and isValid(root.right, root, maxNode)

参考:labuladong 的算法小抄

目录
相关文章
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
50 4
|
1月前
|
算法 索引
LeetCode(搜索插入位置)
如何使用二分查找算法来解决LeetCode上的“搜索插入位置”问题,确保时间复杂度为O(log n),并提供了详细的代码实现和分析。
15 2
|
1月前
|
索引
Leetcode第三十三题(搜索旋转排序数组)
这篇文章介绍了解决LeetCode第33题“搜索旋转排序数组”的方法,该问题要求在旋转过的升序数组中找到给定目标值的索引,如果存在则返回索引,否则返回-1,文章提供了一个时间复杂度为O(logn)的二分搜索算法实现。
19 0
Leetcode第三十三题(搜索旋转排序数组)
|
1月前
【LeetCode 39】700.二叉搜索树中的搜索
【LeetCode 39】700.二叉搜索树中的搜索
16 0
|
3月前
|
算法
LeetCode第81题搜索旋转排序数组 II
文章讲解了LeetCode第81题"搜索旋转排序数组 II"的解法,通过二分查找算法并加入去重逻辑来解决在旋转且含有重复元素的数组中搜索特定值的问题。
LeetCode第81题搜索旋转排序数组 II
|
3月前
|
算法
LeetCode第74题搜索二维矩阵
文章讲解了LeetCode第74题"搜索二维矩阵"的解决方案,利用二分搜索法将问题简化,并通过数学转换找到二维矩阵中的对应元素,展示了将二维问题转化为一维问题的解题技巧。
LeetCode第74题搜索二维矩阵
|
3月前
|
算法
LeetCode第35题搜索插入位置
这篇文章介绍了LeetCode第35题"搜索插入位置"的解题方法,通过使用二分查找法,高效地找到在有序数组中插入一个目标数的最佳位置。
LeetCode第35题搜索插入位置
|
3月前
|
算法
LeetCode第33题搜索旋转排序数组
这篇文章介绍了LeetCode第33题"搜索旋转排序数组"的解题方法,通过使用二分查找法并根据数组的有序性质调整搜索范围,实现了时间复杂度为O(log n)的高效搜索算法。
LeetCode第33题搜索旋转排序数组
|
3月前
|
算法 JavaScript Python
【Leetcode刷题Python】79. 单词搜索和剑指 Offer 12. 矩阵中的路径
Leetcode第79题"单词搜索"的Python解决方案,使用回溯算法在给定的二维字符网格中搜索单词,判断单词是否存在于网格中。
42 4
|
3月前
|
Python
【Leetcode刷题Python】538. 把二叉搜索树转换为累加树
LeetCode上538号问题"把二叉搜索树转换为累加树"的Python实现,使用反向中序遍历并记录节点值之和来更新每个节点的新值。
22 3