题目:
思路分析
- 题目要求返回
任意
二叉搜索子树的最大键值和,显然,这题的思路就是围绕子树是否是BST
和树的遍历方式
展开,提到树,不可避免的想到了递归。 - 首先,判断以
node
节点为根的树是否是二叉搜索树主要有以下步骤:- 以node节点的左右子节点为根的树是否是BST。
- 左子树的最大值小于node.val && 右子树的最小值大于node.val。
- 其次,要获取
最大键值和
,那么最好选择后序遍历
,这样就能够获得左右子节点遍历后返回的结果集。
实现
class Solution {
int maxSum = 0;
public int maxSumBST(TreeNode root) {
traverse(root);
return maxSum;
}
//int[0]:是否是BST,1是,0不是
//int[1]:以node为根的二叉树中节点的最小值
//int[2]:以node为根的二叉树中节点的最大值
//int[3]:BST节点值之和
private int[] traverse(TreeNode node) {
if (node == null) {
return new int[]{1, Integer.MAX_VALUE, Integer.MIN_VALUE, 0};
} else if(node.left == null && node.right == null) {
//当前节点是叶子节点
maxSum = Math.max(maxSum, node.val);
return new int[]{1, node.val, node.val, node.val};
}
int[] left = traverse(node.left);
int[] right = traverse(node.right);
int[] res = new int[4];
if (left[0] == 1 && right[0] == 1) {
//左右子树都是BST
if (left[2] < node.val && right[1] > node.val) {
//左子树的最大值小于node的值,右子树的最小值大于node的值,则以node节点为根的树是BST
res[0] = 1;
res[1] = Math.min(left[1], node.val);
res[2] = Math.max(right[2], node.val);
res[3] = left[3] + right[3] + node.val;
maxSum = Math.max(maxSum, res[3]);
return res;
}
}
res[0] = 0;
return res;
}
}
代码解析
maxSum
初始化为0,根据示例3可知本题要求的监制和最小要求为0。- 遍历时,首先要判断
node
是否是null
,防止递归遍历时产生空指针异常。认为node
是BST(如下图),并且返回最值时使用Integer.MAX_VALUE
,对后续判断树的最值不会产生影响(如下图情况时,以4为根的树满足BST条件,当node.val == 5
时,比较的是最小值,所以不会产生影响,其余位置同理分析即可),键值和为0,即不为后续的键值和产生影响。
- 如果
node
是叶子节点,那么node
一定是BST。 - 如果以
node
为根的树不是BST,只需要res[0] = 0
即可,其余值并不会被使用到。