# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def maxSumBST(self, root: TreeNode) -> int:
self.max_sum = 0
def postorder(node):
if not node:
# is_bst, min, max, sum
return (True, float('inf'), float('-inf'), 0)
l_bst, l_min, l_max, l_sum = postorder(node.left)
r_bst, r_min, r_max, r_sum = postorder(node.right)
if l_bst and r_bst and l_max < node.val < r_min:
total = l_sum + r_sum + node.val
self.max_sum = max(self.max_sum, total)
return (True, min(l_min, node.val), max(r_max, node.val), total)
else:
return (False, 0, 0, 0)
postorder(root)
return self.max_sum
// Definition for a binary tree node.
// struct TreeNode {
// int val;
// TreeNode *left;
// TreeNode *right;
// TreeNode(int x) : val(x), left(NULL), right(NULL) {}
// };
class Solution {
public:
int maxSum = 0;
// returns {isBST, min, max, sum}
vector<int> postorder(TreeNode* node) {
if (!node) return {1, INT_MAX, INT_MIN, 0};
auto l = postorder(node->left);
auto r = postorder(node->right);
if (l[0] && r[0] && l[2] < node->val && node->val < r[1]) {
int sum = l[3] + r[3] + node->val;
maxSum = max(maxSum, sum);
return {1, min(l[1], node->val), max(r[2], node->val), sum};
}
return {0, 0, 0, 0};
}
int maxSumBST(TreeNode* root) {
postorder(root);
return maxSum;
}
};
// Definition for a binary tree node.
// public class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int x) { val = x; }
// }
class Solution {
private int maxSum = 0;
// returns int[]{isBST, min, max, sum}
private int[] postorder(TreeNode node) {
if (node == null) return new int[]{1, Integer.MAX_VALUE, Integer.MIN_VALUE, 0};
int[] l = postorder(node.left);
int[] r = postorder(node.right);
if (l[0] == 1 && r[0] == 1 && l[2] < node.val && node.val < r[1]) {
int sum = l[3] + r[3] + node.val;
maxSum = Math.max(maxSum, sum);
return new int[]{1, Math.min(l[1], node.val), Math.max(r[2], node.val), sum};
}
return new int[]{0, 0, 0, 0};
}
public int maxSumBST(TreeNode root) {
postorder(root);
return maxSum;
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
var maxSumBST = function(root) {
let maxSum = 0;
// returns [isBST, min, max, sum]
function postorder(node) {
if (!node) return [true, Infinity, -Infinity, 0];
let [lBST, lMin, lMax, lSum] = postorder(node.left);
let [rBST, rMin, rMax, rSum] = postorder(node.right);
if (lBST && rBST && lMax < node.val && node.val < rMin) {
let total = lSum + rSum + node.val;
maxSum = Math.max(maxSum, total);
return [true, Math.min(lMin, node.val), Math.max(rMax, node.val), total];
}
return [false, 0, 0, 0];
}
postorder(root);
return maxSum;
};
Given the root of a binary tree, your task is to find the maximum sum of all keys in any subtree which is also a Binary Search Tree (BST). A subtree of a node is considered a BST if:
0
.
root
(the root node of a binary tree)
To solve this problem, we need to consider every possible subtree in the binary tree and check if it's a valid BST. If it is, we compute the sum of its nodes and keep track of the maximum found.
The brute-force approach would be to check every node as a root, validate if its subtree is a BST (which itself can be O(n)), and then sum its values. But this would be very inefficient, especially for large trees.
Instead, we can use a more efficient approach by processing the tree in a bottom-up manner (post-order traversal). For each node, we can gather information from its left and right subtrees about:
The optimized solution uses a post-order traversal (left-right-root) to process each node only once, collecting all the necessary information from its children before processing the parent. Here’s how it works step-by-step:
Sample Input:
Consider the following binary tree:
1 / \ 4 3 / \ \ 2 4 5 / \ 4 6Step-by-Step Trace:
20
.
Brute-force Approach:
For each node, check if its subtree is a BST and sum its values. For each node, this takes O(n) time, leading to O(n^2) total time for n nodes.
Optimized Approach (Post-order Traversal):
This problem is elegantly solved by using a post-order traversal to gather and propagate BST properties up the tree. By checking BST validity and computing subtree sums as we return from recursion, we efficiently determine the maximum sum of any BST subtree. The key insight is to collect all necessary information from children before processing the parent, enabling an O(n) solution that is both clean and intuitive.