Start learning free

LESSON 482 OF 671 · BINARY TREES

Maximum Sum BST in Binary Tree: Java Solution and Time Complexity Analysis

Practice O(n2) Read the full explanation

You get the root of a binary tree. Return the largest sum of values in a subtree that is a binary search tree (BST).

A subtree is a node together with everything below it. It is a BST when this holds at each of its nodes:

  • every value in the node's left subtree is smaller than the node's value,
  • every value in its right subtree is larger.

An empty tree also counts as a BST, with a sum of 0. So the answer is never below 0.

The trees below are listed level by level, top to bottom and left to right. A missing child is written as null.

 

Example 1:

6 9 3 4 11 2 1 5

Input: root = [6,9,3,4,11,null,2,1,5]
Output: 30
Explanation: The blue subtree starts at 9.
It is a BST: 1 < 4 < 5 < 9 < 11.
Its sum is 9 + 4 + 11 + 1 + 5 = 30.
The whole tree is not a BST: 9 is left of 6 but larger.
The subtree from 3 down is not a BST: 2 is right of 3 but smaller.

Example 2:

-5 -8 4 -9 7

Input: root = [-5,-8,4,-9,7]
Output: 7
Explanation: The subtree from -8 down is a BST, but its sum is -10.
The whole tree is not a BST: 7 is left of -5 but larger.
The best BST is the single blue node 7.

Example 3:

Input: root = [-3,-6,-1]
Output: 0
Explanation: The whole tree is a BST, but every value is negative.
So any BST with nodes in it has a sum below 0.
The empty tree, with sum 0, is the best.

 

Constraints:

  • 1 to 25,000 nodes.
  • Each value is from -10,000 to 10,000.
  • The tree can be up to 10,000 levels deep.
STEP 1 OF 21
    Ctrl + Enter to check

    JAVA · BINARY TREES

    Max Sum Bst in Java, explained

    Understanding the Problem

    The core challenge of this problem is to identify the largest sum of keys in any subtree that is a valid Binary Search Tree (BST). A BST is defined by the property that for any node, all nodes in its left subtree have keys less than the node's key, and all nodes in its right subtree have keys greater than the node's key. This problem is significant in various applications such as database indexing, where BST properties are leveraged for efficient data retrieval.

    Approach

    To solve this problem, we need to traverse the tree and check each subtree to determine if it is a valid BST and calculate its sum. A naive approach would involve checking each subtree individually, which would be highly inefficient. Instead, we can use a post-order traversal to gather information about each subtree and determine if it forms a valid BST.

    Naive Solution

    The naive solution involves checking each node and its subtrees to see if they form a valid BST and then calculating the sum. This approach is not optimal due to its high time complexity.

    Optimized Solution

    An optimized solution involves using a post-order traversal to gather information about each subtree. For each node, we can determine if its left and right subtrees are valid BSTs and use this information to check if the current subtree is a valid BST. We can also keep track of the sum of keys in each subtree and update the maximum sum accordingly.

    Algorithm

    The algorithm involves a post-order traversal of the tree. For each node, we gather information about its left and right subtrees, including whether they are valid BSTs, their sums, and their minimum and maximum values. Using this information, we can determine if the current subtree is a valid BST and calculate its sum.

    Step-by-Step Breakdown

    1. Perform a post-order traversal of the tree.
    2. For each node, gather information about its left and right subtrees.
    3. Check if the current subtree is a valid BST using the gathered information.
    4. Calculate the sum of keys in the current subtree if it is a valid BST.
    5. Update the maximum sum if the current subtree's sum is greater than the previous maximum sum.

    Code Implementation

    class Solution {
        // Class to store information about each subtree
        class SubtreeInfo {
            boolean isBST;
            int sum;
            int min;
            int max;
            
            SubtreeInfo(boolean isBST, int sum, int min, int max) {
                this.isBST = isBST;
                this.sum = sum;
                this.min = min;
                this.max = max;
            }
        }
        
        private int maxSum = 0;
        
        public int maxSumBST(TreeNode root) {
            postOrderTraversal(root);
            return maxSum;
        }
        
        private SubtreeInfo postOrderTraversal(TreeNode node) {
            if (node == null) {
                return new SubtreeInfo(true, 0, Integer.MAX_VALUE, Integer.MIN_VALUE);
            }
            
            SubtreeInfo left = postOrderTraversal(node.left);
            SubtreeInfo right = postOrderTraversal(node.right);
            
            if (left.isBST && right.isBST && node.val > left.max && node.val < right.min) {
                int sum = node.val + left.sum + right.sum;
                maxSum = Math.max(maxSum, sum);
                return new SubtreeInfo(true, sum, Math.min(node.val, left.min), Math.max(node.val, right.max));
            } else {
                return new SubtreeInfo(false, 0, 0, 0);
            }
        }
    }
    

    Complexity Analysis

    The time complexity of the optimized solution is O(n), where n is the number of nodes in the tree. This is because we perform a post-order traversal of the tree, visiting each node exactly once. The space complexity is O(h), where h is the height of the tree, due to the recursion stack.

    Edge Cases

    Potential edge cases include:

    • Empty tree: The output should be 0.
    • Tree with all negative values: The output should be 0, as no valid BST can have a positive sum.
    • Tree with only one node: The output should be the value of that node.

    Testing

    To test the solution comprehensively, we should include a variety of test cases:

    • Simple cases with small trees.
    • Cases with larger trees to test performance.
    • Edge cases such as empty trees and trees with negative values.

    Thinking and Problem-Solving Tips

    When approaching such problems, it is important to:

    • Understand the problem requirements and constraints thoroughly.
    • Break down the problem into smaller sub-problems.
    • Consider different approaches and their trade-offs.
    • Practice solving similar problems to improve problem-solving skills.

    Conclusion

    In this blog post, we discussed the problem of finding the maximum sum of keys in any subtree that is a valid BST. We explored a naive solution and an optimized solution using post-order traversal. We also analyzed the time and space complexity of the solution and discussed potential edge cases and testing strategies. Understanding and solving such problems is crucial for improving problem-solving skills and preparing for technical interviews.

    Additional Resources

    For further reading and practice, consider the following resources:

    Keep going with Java650+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free