LeetCode 1373.二叉搜索树的最大键值和

本文介绍了如何找到一棵二叉树中键值和最大的二叉搜索子树。通过后序遍历,检查每个节点是否构成BST,并计算节点和,最终找到最大键值和。代码实现使用C++,展示了如何判断BST和更新最大和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题目

【Hard】给你一棵以 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 的单节点子树是和最大的二叉搜索树。
在这里插入图片描述

思路

首先想到二叉树的两种解题框架:

  1. 通过子问题的解推导出答案(递归)
  2. 通过遍历一遍树找出答案

很明显,子树是BST时当前树不一定是BST,所以第一种情况不适用,本题采用遍历方法实现。

既然要遍历,就要考虑以什么样的遍历顺序遍历,本题中要找最大键值和,对于每个节点来说,需要做的事有:

  1. 判断以自己为根的树是不是BST
  2. 如果是,求解以自己为根的树的键值和
  3. 与目前键值和比较,更新结果为较大的

其中,1.可以拆解为两步:

  • 判断左右子树是不是BST
  • 如果左右子树都是,判断加入当前root后还是不是(即判断是否左小右大)

上述思路很明显要先求解子树的相关值才能确定当前节点的相关值,所以确定以后序遍历实现,其他遍历顺序也可以实现,但一定没有后序遍历有效,复杂度更低。

经过上述分析,总结本题思路:

  1. 后序遍历一遍二叉树

  2. 遍历时对于每个节点,判断:

    (1) 左右子树是不是BST
    (2)加入当前节点还是不是BST

  3. 上述两个条件都满足的情况下:求以当前节点为根的树的节点和

  4. 当前节点的键值和与目前最大键值和maxSum比较,更新maxSum为较大值。

这样,经过一次遍历以后,maxSum就是最终的最大键值和。

代码实现(C++)

class Solution {
public:
    int maxSum = 0; //最大和
    int maxSumBST(TreeNode* root) {
        traverse(root);
        return maxSum;
    }
	
	// 返回的vector分别保存:  0. 是不是BST; 1.当前树的最小值; 2.当前树的最大值; 3.当前树节点和
    vector<int> traverse(TreeNode* root) {
        if (root == nullptr) return vector<int> {1, INT_MAX, INT_MIN, 0};

        vector<int> left = traverse(root->left);
        vector<int> right = traverse(root->right);

        vector<int> res(4);
        if (left[0] == 1 && right[0] == 1  && root->val > left[2] && root->val < right[1]) {
            res[0] = 1;
            res[1] = min(left[1], root->val);
            res[2] = max(right[2], root->val);
            res[3] = left[3] + right[3] + root->val;
            maxSum = max(res[3], maxSum);
        } else {
            res[0] = 0;
        }

       return res;
    }
};

总结

此题的关键在于后序遍历顺序的确定,一般需要用到左右子树的计算结果时,要用后序遍历。
如果用其他遍历顺序,一定需要在递归中调用其他递归函数,要尽量避免这种情况,有时候换一种合理的遍历顺序就能够很好地优化代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值