二叉搜索子树的最大键值和
难度:
标签:
题目描述
给你一棵以 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 的单节点子树是和最大的二叉搜索树。
示例 3:
输入:root = [-4,-2,-5] 输出:0 解释:所有节点键值都为负数,和最大的二叉搜索树为空。
示例 4:
输入:root = [2,1,3] 输出:6
示例 5:
输入:root = [5,4,8,3,null,6,3] 输出:7
提示:
- 每棵树有
1
到40000
个节点。 - 每个节点的键值在
[-4 * 10^4 , 4 * 10^4]
之间。
代码结果
运行时间: 173 ms, 内存: 34.7 MB
/*
题目思路:
1. 使用后序遍历遍历二叉树,以便处理每个节点时先处理其子节点。
2. 对于每个节点,计算其作为二叉搜索树的可能性,包括最大和。
3. 返回所有可能二叉搜索树的最大和。
使用 Java Stream 的方法。
*/
import java.util.Optional;
import java.util.stream.Stream;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
private class Result {
int min, max, sum;
boolean isBST;
Result(int min, int max, int sum, boolean isBST) {
this.min = min;
this.max = max;
this.sum = sum;
this.isBST = isBST;
}
}
private int maxSum = 0;
public int maxSumBST(TreeNode root) {
postOrder(root);
return maxSum;
}
private Result postOrder(TreeNode node) {
if (node == null) return new Result(Integer.MAX_VALUE, Integer.MIN_VALUE, 0, true);
Result left = postOrder(node.left);
Result right = postOrder(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 Result(Math.min(node.val, left.min), Math.max(node.val, right.max), sum, true);
} else {
return new Result(0, 0, 0, false);
}
}
public Stream<TreeNode> stream(TreeNode root) {
if (root == null) return Stream.empty();
return Stream.concat(Stream.of(root), Stream.concat(stream(root.left), stream(root.right)));
}
}
解释
方法:
本题解采用深度优先搜索(DFS)方法来找出具有最大键值和的二叉搜索子树。对于每个节点,我们检查其是否能形成一个二叉搜索树(BST)。具体来说,DFS函数返回一个三元组:(子树的和, 子树的最小值, 子树的最大值)。若某个子树不是BST,我们使用一个非常小的标记值(float('-inf'))来标记其和,这样其父节点就不会错误地认为它可以形成BST。在递归过程中,我们更新全局变量ans来保持迄今为止找到的最大键值和。这种方法确保每个节点最多被访问一次。
时间复杂度:
O(n)
空间复杂度:
O(h),其中h是树的高度
代码细节讲解
🦆
为什么在判断子树是否为二叉搜索树时,需要同时考虑左子树的最大值和右子树的最小值?
▷🦆
DFS函数中使用float('-inf')来标记非BST子树的和,这种做法有无可能影响整体算法的正确性?例如在处理包含负数值节点的树时。
▷🦆
在递归过程中,为什么没有明显处理节点值为null的情况,这是否会影响函数的正确执行?
▷🦆
代码中对于叶子节点和非叶子节点的处理逻辑有所不同,能否详细解释为什么这样处理?
▷