[LeetCode] 1373. Maximum Sum BST in Binary Tree 二叉搜索子树的最大键值和


Given a binary tree `root`, return *the maximum sum of all keys of any sub-tree which is also a Binary Search Tree (BST)*.

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than the node's key.
  • The right subtree of a node contains only nodes with keys greater than the node's key.
  • Both the left and right subtrees must also be binary search trees.

Example 1:

Input: root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]
Output: 20
Explanation: Maximum sum in a valid Binary search tree is obtained in root node with key equal to 3.

Example 2:

Input: root = [4,3,null,1,2]
Output: 2
Explanation: Maximum sum in a valid Binary search tree is obtained in a single root node with key equal to 2.

Example 3:

Input: root = [-4,-2,-5]
Output: 0
Explanation: All values are negatives. Return an empty BST.

Constraints:

  • The number of nodes in the tree is in the range [1, 4 * 10^4].
  • -4 * 10^4 <= Node.val <= 4 * 10^4

这道题说是给了一个二叉树,让找出子树中最大的二叉搜索树 Binary Search Tree (BST),并返回该子树的所有结点之和。这道题又是关于二叉搜索树的题,BST 也算是我们的老朋友了,LeetCdoe 上相关题目少说也有二十多道了,想必大家也并不陌生了。核心的一点就是当前的结点值一定要大于左子树中的最大值,一定要小于右子树中的最小值,并且左右子树都必须也要是 BST。关于验证 BST 的题目可以参见之前这道 Validate Binary Search Tree,其核心思想就是利用递归写法的中序遍历去验证 左<根<右 的这条性质。这道题并不是简单的要去验证 BST,而是要找到最大的子二叉搜索树,就是说关注点就在子树这里,那么天然适合用后序遍历去做,为啥呢,因为后序遍历是左右根的顺序,先遍历左右子结点,最后才是根结点,等到根结点的时候,左右子树的信息都已经有了,不管是统计子树的结点个数,还是结点之和都很方便了。

其实跟这道题最像的是之前的那道 Largest BST Subtree,求的就是最大 BST 子树的结点的个数,只不过这里换成了结点之和。这里还是采用递归写法的后序遍历来做,使用一个全局变量 res 来记录遍历过程中最大的 BST 子树的结点之和。这里使用的递归的子函数的返回值是一个长度为3的数组,三个值分别是当前 BST 子树中的最小值,最大值,还有结点之和。这三个信息都是特别重要的,缺一不可,最大值和最小值是持续验证子树是否是 BST 的关键,而结点之和是用来更新全局 res 的值的。在递归函数中,首先判空,如果当前结点为空,则返回默认的三个值,整型数最大值,整型数最小值,和0,特别要注意的就是这里的第一个数字我们定义的是子树中的最小值,而这里却要传整型数的最大值,这是为啥呢,后面会解释。接下来就是后序遍历的传统写法,先对左右子结点调用递归函数,将返回的数组分别存在 left 和 right 数组变量中。

然后就是关键的验证 BST 的步骤了,对于不是 BST 子树的根结点,返回数组会为空,这样的话,只要判断 left 或者 right 为空,就表示当前根结点的左子树或者右子树不是 BST,则当前二叉树也不是 BST。若 left 和 right 不为空,还要继续验证 左<根<右 的这条性质。左子树的最大值存在了 left[1] 中,若根结点小于等于 left[1],则当前二叉树不是 BST,同理,右子树的最小值存在了 right[0] 中,若根结点大于等于 right[0],则当前二叉树也不是 BST,返回空数组即可。这里回过头说一下为啥遇到空结点,要把整型数最大值放到第一个,整型数最小值放在第二个位置。当左子结点不存在的时候,左子树最大值 left[1] 设置为整型数最小值,当前根结点一定会大于这个整型数最小值,同理,当右子结点不存在时,右子树最小值 right[0] 设置为整型数最大值,当前根结点一定会小于这个整型数最大值,整个逻辑不用变,都可以通过。

经过了 BST 性质的验证,则当前子树是 BST,计算当前子树的结点之和,用根结点的值加上 left[2] 和 right[2] 即可,然后用 sum 更新最终结果 res 的值。接下来计算当前子树的最小值 mn,取根结点值和 left[0] 中的较小值,同理,当前子树的最大值 mx,取根结点值和 right[1] 中的较大值,将 mn, mx 和 sum 组成一个数组返回即可,参见代码如下:


class Solution {
public:
    int maxSumBST(TreeNode* root) {
        int res = 0;
        dfs(root, res);
        return res;
    }
    vector<int> dfs(TreeNode* node, int& res) {
        if (!node) return {INT_MAX, INT_MIN, 0};
        vector<int> left = dfs(node->left, res);
        vector<int> right = dfs(node->right, res);
        if(left.empty() || right.empty() || node->val <= left[1] || node->val >= right[0]) {
            return {};
        }
        int sum = node->val + left[2] + right[2];
        res = max(res, sum);
        int mn = min(node->val, left[0]);
        int mx = max(node->val, right[1]);
        return {mn, mx, sum};
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1373


类似题目:

Validate Binary Search Tree

Binary Tree Postorder Traversal

Find Mode in Binary Search Tree

Largest BST Subtree


参考资料:

https://leetcode.com/problems/maximum-sum-bst-in-binary-tree

https://leetcode.com/problems/maximum-sum-bst-in-binary-tree/solutions/531822/java-post-order-traverse-with-comment-cl-f0vl/

https://leetcode.com/problems/maximum-sum-bst-in-binary-tree/solutions/1126183/c-recursion-easy-to-understand-by-divyan-6fa0/


LeetCode All in One 题目讲解汇总(持续更新中...)

posted @ 2026-08-23 16:01  Grandyang  阅读(7)  评论(0)    收藏  举报
Fork me on GitHub