1373. 二叉搜索子树的最大键值和
题意
给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。
二叉搜索树的定义如下:
任意节点的左子树中的键值都 小于 此节点的键值。
任意节点的右子树中的键值都 大于 此节点的键值。
任意节点的左子树和右子树都是二叉搜索树。
示例
输入:root = [1,4,3,2,4,2,5,null,null,null,null,null,null,4,6]
输出:20
解释:键值为 3 的子树是和最大的二叉搜索树。
输入: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
题解
首先这道题目属于对于二叉搜索树的路径求值,所以一般的思路还是会用到递归和动态规划。
首先想到的是后序遍历,因为需要知道当前的节点所构成的二叉树是不是一个二叉搜索树,所以需要对其进行判断,二叉搜索树的条件是对于左子树的任何一个节点均小于根节点,而右子树的任何一个节点均大于根节点。所以就会用到以当前节点为遍历位置,对其左子树和右子树进行递归处理,只有当左子树与右子树均为二叉搜索树的时候才会与根进行判断是否符合二叉搜索树。
需要记录的数据为当前的节点树是否为二叉搜索树,其次是以当前节点的树的节点最大值和最小值。因为二叉搜索树的根节点大于左子树小于右子树。另外还要记录当前的路径。
可以采用结构体:
struct ret
{
int bool;
int max;
int min;
int sum;
}
也可以采用数组:
vector<int>{1,INT_MAX,INT_MIN,0}
class Solution {
public:
int maxnum = 0;
int maxSumBST(TreeNode* root) {
bsf(root);
return maxnum;
}
vector<int> bsf(TreeNode* root){
if(root == nullptr){
return vector<int>{1,INT_MAX,INT_MIN,0};//判断当前节点是否为空,如果是的话,则为二叉搜索树,
//但是因为没有子节点,所以当采用后序遍历的时候,需要和父节点比较,选择最小值,而右节点需要选择最大值
}
vector<int> left = bsf(root->left);
vector<int> right = bsf(root->right);
vector<int> res(4);
if(left[0]==1 && right[0]==1 && right[1]> root->val && left[2]< root->val)//右子树最小值大于根,左子树最大值小于根
{
res[0] = 1;
res[1]=min(left[1], root->val);//有可能左节点为空,那么默认值为MaxInteger
res[2]=max(right[2], root->val);
res[3]= root->val+left[3]+right[3];
maxnum=max(res[3],maxnum);
}
else {
res[0]=0;//非BST
}
return res;
}
};