LeetCode #1373 Hard

Maximum Sum BST in Binary Tree

Maximum Sum BST in Binary Tree is LeetCode 1373 (Hard). You are given the root of a binary tree that is not necessarily a binary search tree. Among all of its subtrees that are valid BSTs, return the largest sum of keys.

  • A subtree means a node together with all of its descendants; you cannot cut branches off.
  • A valid BST has every key in the left subtree strictly less than the node's key and every key in the right subtree strictly greater, and both subtrees are BSTs themselves. Duplicate keys therefore break the property.
  • An empty tree counts as a BST with sum 0, so the answer is never negative.
Constraints
  • The number of nodes in the tree is in the range [1, 4 * 10⁴].
  • -4 * 10⁴ <= Node.val <= 4 * 10⁴
bstdfsdp
Open on LeetCode ↗
02

Intuition

Testing every node separately walks each subtree again, which is O(n²) on a tall tree. Turn it around and let every node report upward instead.

To decide whether a node roots a BST, it needs only four facts about each child's subtree: is it a BST, its smallest key, its largest key, and its sum. Then left.max < node.val < right.min settles it in O(1), and the node reports its own four facts to its parent.

A post-order DFS produces these bottom-up in one pass, and every node that qualifies offers its sum as a candidate answer, even if an ancestor later fails.

How to spot this pattern

When a question asks for the best subtree with some property, and the property of a node depends on facts about its children, return a small tuple from a post-order DFS. Here the tuple is (isBST, min, max, sum). Validate Binary Search Tree uses the same min/max reasoning top-down; Largest BST Subtree uses exactly this tuple with a node count instead of a sum.

03

Approach

Try it first

Before reading on: for a node whose left child is 3 and right child is 7, is checking 3 < node < 7 enough to call it a BST? Build a small counterexample. Then decide what an empty child should report so a leaf passes the check.

1

Define what each call returns

dfs(node) returns (isBST, lo, hi, total): whether the subtree is a BST, its smallest and largest keys, and its sum.

2

Report the empty tree as a passing BST

dfs(None) returns (True, +∞, −∞, 0). With the infinities reversed, the parent's test left.hi < val < right.lo always holds on the empty side.

3

Combine the two children after visiting them

If both children are BSTs and left.hi < node.val < right.lo, the node roots a BST: its sum is left.total + right.total + node.val, its smallest key is min(left.lo, node.val) and its largest max(right.hi, node.val).

4

Record every BST's sum, and fail the rest

Update a global best whenever a node roots a BST, before returning. Otherwise return isBST = False; every ancestor then fails too, while the sums already recorded below it stay counted.

04

Maximum Sum BST in Binary Tree solution in Python | C++ | Java

▶1class Solution:
▶2 def maxSumBST(self, root: Optional[TreeNode]) -> int:
▶3 best = 0
▶4 
▶5 def dfs(node):
▶6 nonlocal best
▶7 if not node:
▶8 return True, float("inf"), float("-inf"), 0
▶9 lb, llo, lhi, lsum = dfs(node.left)
▶10 rb, rlo, rhi, rsum = dfs(node.right)
▶11 if lb and rb and lhi < node.val < rlo:
▶12 total = lsum + rsum + node.val
▶13 best = max(best, total)
▶14 return True, min(llo, node.val), max(rhi, node.val), total
▶15 return False, 0, 0, 0
▶16 
▶17 dfs(root)
▶18 return best
best0143242546left child reportsright child reportsleft max < nodenode < right minbest = 0 → post-order DFS from the leaves
best0the empty tree is a BST with sum 0
nodes9each visited once
Plan. A node can only be judged once both children have reported, so the DFS runs post-order, leaves first. Each report carries four facts: is the subtree a BST, its smallest key, its largest key and its sum. best starts at 0, not −∞, because an empty subtree is a valid BST.
best21432Σ242546left: emptymin+∞max−∞sum0right: emptymin+∞max−∞sum0−∞ < 2 ✓2 < +∞ ✓node 2 is a BST, sum 2 → best = 2
node2roots a BST
returnsmin 2, max 2, sum 2to the parent
best2improved
2 is a leaf. Both empty children report min +∞ and max −∞, so both checks pass automatically: a BST with sum 2. That beats best, which becomes 2.
best41432Σ24Σ42546left: emptymin+∞max−∞sum0right: emptymin+∞max−∞sum0−∞ < 4 ✓4 < +∞ ✓node 4 is a BST, sum 4 → best = 4
node4roots a BST
returnsmin 4, max 4, sum 4to the parent
best4improved
4 is a leaf. Both empty children report min +∞ and max −∞, so both checks pass automatically: a BST with sum 4. That beats best, which becomes 4.
best414✗32Σ24Σ42546left: node 2min2max2sum2right: node 4min4max4sum42 < 4 ✓4 < 4 ✗node 4 is not a BST
node4not a BST
returnsnot a BSTto the parent
best4unchanged
The smallest key on the right is 4, which is not above 4. Every right key must be strictly larger, so 4 does not root a BST.
best414✗32Σ24Σ42Σ2546left: emptymin+∞max−∞sum0right: emptymin+∞max−∞sum0−∞ < 2 ✓2 < +∞ ✓node 2 is a BST, sum 2
node2roots a BST
returnsmin 2, max 2, sum 2to the parent
best4unchanged
2 is a leaf. Both empty children report min +∞ and max −∞, so both checks pass automatically: a BST with sum 2. Not more than best (4).
best414✗32Σ24Σ42Σ254Σ46left: emptymin+∞max−∞sum0right: emptymin+∞max−∞sum0−∞ < 4 ✓4 < +∞ ✓node 4 is a BST, sum 4
node4roots a BST
returnsmin 4, max 4, sum 4to the parent
best4unchanged
4 is a leaf. Both empty children report min +∞ and max −∞, so both checks pass automatically: a BST with sum 4. Not more than best (4).
best614✗32Σ24Σ42Σ254Σ46Σ6left: emptymin+∞max−∞sum0right: emptymin+∞max−∞sum0−∞ < 6 ✓6 < +∞ ✓node 6 is a BST, sum 6 → best = 6
node6roots a BST
returnsmin 6, max 6, sum 6to the parent
best6improved
6 is a leaf. Both empty children report min +∞ and max −∞, so both checks pass automatically: a BST with sum 6. That beats best, which becomes 6.
best1514✗32Σ24Σ42Σ25Σ154Σ46Σ6left: node 4min4max4sum4right: node 6min6max6sum64 < 5 ✓5 < 6 ✓node 5 is a BST, sum 15 → best = 15
node5roots a BST
returnsmin 4, max 6, sum 15to the parent
best15improved
Both children are BSTs, the left max 4 is below 5 and the right min 6 is above it, so 5 roots a BST with sum 15. New best: 15.
best2014✗3Σ202Σ24Σ42Σ25Σ154Σ46Σ6left: node 2min2max2sum2right: node 5min4max6sum152 < 3 ✓3 < 4 ✓node 3 is a BST, sum 20 → best = 20
node3roots a BST
returnsmin 2, max 6, sum 20to the parent
best20improved
Both children are BSTs, the left max 2 is below 3 and the right min 4 is above it, so 3 roots a BST with sum 20. New best: 20.
best201✗4✗3Σ202Σ24Σ42Σ25Σ154Σ46Σ6left: node 4not a BSTright: node 3min2max6sum20no checkfailsnode 1 is not a BST
node1not a BST
returnsnot a BSTto the parent
best20unchanged
The left subtree of 1 is not a BST, so this one cannot be either, whatever the keys. It reports failure, and every ancestor will fail the same way.
best201✗4✗3Σ202Σ24Σ42Σ25Σ154Σ46Σ6return 20, the BST rooted at 3
answer20subtree rooted at 3
visits9one pass, O(n)
Answer 20. The green subtree rooted at 3 is the BST with the largest sum. It was recorded the moment that node qualified, so the failures above it could not erase it.
05

Common pitfalls

Comparing with the children instead of the subtree extremes

✗ Wrong
if node.left.val < node.val < node.right.val:
✓ Right
if lb and rb and lhi < node.val < rlo:

The BST rule covers the whole subtree. Take root 5 with children 3 and 8, and 9 as the right child of 3. Both direct children look fine, but 9 sits on the left of 5. Only the left subtree's maximum (9) catches it.

Allowing equal keys

✗ Wrong
if lb and rb and lhi <= node.val <= rlo:
✓ Right
if lb and rb and lhi < node.val < rlo:

A BST here needs strictly smaller keys on the left and strictly larger on the right. With <=, the tree [5, 5, 5] counts as one BST and returns 15; the right answer is 5, a single leaf.

Starting the answer at negative infinity

✗ Wrong
best = float("-inf")
✓ Right
best = 0

The empty tree is a BST with sum 0, so 0 is always reachable. When every key is negative, the -inf start returns the least negative single node instead of 0.

06

Edge cases

The best BST sits under an ancestor that fails

In [4, 3, null, 1, 2] no subtree above the leaves is a BST, yet the answer is 2. The sum is recorded in best the moment a node qualifies, so a failure higher up cannot erase it; returning only the root's result would lose it.

07

Complexity

Time
O(n)
Space
O(h)
Each node is visited once and combines two fixed-size tuples in O(1). The recursion stack is as deep as the tree: O(log n) when balanced, O(n) for a chain. The maximum sum BST in binary tree Python code returns a 4-tuple; C++ and Java return a small array or struct.
08

Maximum Sum BST vs Largest BST Subtree

The two problems run the same post-order pass. They differ in what a qualifying subtree is worth, and that changes the floor of the answer.

ProblemScore of a BST subtreeSmallest possible answer
Maximum Sum BST in Binary Tree (LeetCode 1373)sum of its keys (can be negative)0, the empty tree
Largest BST Subtree (LeetCode 333)number of nodes1, any single node
09

Maximum Sum BST in Binary Tree FAQ

Why does an empty subtree return +∞ as its minimum and −∞ as its maximum?

The parent checks left.max < val < right.min. A missing child must never make that check fail, so it reports the most permissive bounds: nothing is below −∞ or above +∞. The combined min and max then come out right too, because min(+∞, val) is val.

Can you walk through a maximum sum bst in binary tree example?

In LeetCode's first example the root 1 and its left child 4 are not BSTs (4 has a right child equal to 4). The right child 3 has children 2 and 5, and 5 has children 4 and 6. Those form a BST whose keys sum to 3 + 2 + 5 + 4 + 6 = 20, the answer.