二叉树搜索子树的最大键值和

Posted ChangZhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树搜索子树的最大键值和相关的知识,希望对你有一定的参考价值。

什么时候使用后序遍历呢?
如果当前节点要做的事情需要通过左右子树的计算结果推导出来,就要用到后序遍历
二叉树相关题目最核心的的思路就是明确当前节点需要做的事情是什么???
1.我肯定得知道左右子树是不是合法的BST,如果这俩儿子有一个不是BST,以我为根的这棵树肯定不是BST。
2.如果左右子树都是合法的BST,我得瞅瞅左右子树加上自己还是不是合法的BST,因为按照BST的定义,当前节点的值应该大于左子树的最大值,小于右子树的最小值,否则就破坏了BST的性质。
3.因为题目要计算最大的节点之和,如果左右子树加上我自己还是一棵合法的BST,也就是说以我为根的整棵树是一棵BST,那我需要知道我们这棵的所有节点之和是多少。
站在当前节点的视角,需要知道以下具体信息:
1.左右子树是否是BST。
2.左子树的最大值和右子树的最小值。
3.左右子树的节点值之和。
尝试用伪码写出算法的大致逻辑:

//全局变量,记录BST最大节点值和
int maxSum=0;

//遍历二叉树
void traverse(TreeNode root){
//base case
if(root==null){
return;
}

//前序遍历代码
//判断左右子树是不是BST
if(!isBST(root.left)||!isBST(root.right)){
goto next;
}

//计算左子树的最大值和右子树的最小值
int leftMax=findMax(root.left);
int rightMin=findMin(root.right);

//判断以root节点为根的树是不是BST
if(root.val<=leftMax||root.val>=rightMin){
goto next;
}

//如果条件都符合,计算当前BST的节点之和
int leftSum=findSum(root.left);
int rightSum=findSum(root.right);
int rootSum=leftSum+rightSum+root.val;
//计算BST节点的最大和
this.maxSum=Math.max(maxSum,rootSum);

//递归左右子树
next:
traverse(root.left);
traverse(root.right);
}

//计算以root为根的二叉树的最大值
int findMax(TreeNode root){}

//计算以root为根的二叉树的最小值
int findMin(TreeNode root){};

//计算以root为根的二叉树的节点和
int findSum(TreeNode root){};

//判断以root为根的二叉树是否是BST
boolean isBST(TreeNode root){}

其中四个辅助函数比较简单,其中只有判断合法BST的函数稍有技术含量,前文二叉搜索树操作集锦
稍作分析就会发现,这几个辅助函数都是递归函数,都要遍历输入的二叉树,外加traverse函数本身的递归,可以说是递归上加递归,所以复杂度很高
只要把前序遍历变成后序遍历,让traverse函数把辅助函数做的事顺便做掉

int maxSum=0;

int [] traverse(TreeNode root){
int[] left=traverse(root.left);
int[] right=traverse(root.right);
}

traverse(root)返回一个大小为4的int数组,我们暂且称他为res,其中:
res[0]-记录以root为根的二叉树是否是BST,若为1则说明是BST,若为0则说明不是BST。
res[1]-记录以root为根的二叉树的所有节点中的最小值
res[2]-记录以root为根二叉树所有节点中的最大值
res[3]-记录以root为根的二叉树所有节点值之和
我们要视图通过left和right正确地导出res数组

int[] traverse(TreeNode root){
if(root==null){
return new int[]{
1,Integer>MAX_VALUE,Integer>MIN_VALUE,0
};
}
//递归计算左右子树
int [] left=traverse(root.left);
int [] right=traverse(root.right);

int[] res=new int[4];
//这个if在判断以root为根的二叉树是不是BST
if(left[0]==1&&right[0]==1&&root.val>left[2]&&root.val<right[1]){
//以root为根的是二叉树是BST
res[0]=1;
res[1]=Math.min(left[1],root.val);
res[2]=Math.max(right[2],root.val);
res[3]=left[3]+right[3]+root.val;
maxSum=Math.max(maxSum,res[3]);
}else{
res[0]=0;
}
return res;
}

这后序遍历也不是乱用的,这里为什么能用呢???
以root为根的二叉树的节点之和,是不是可以通过左右子树的和加上root.val计算出来?
以root为根的二叉树的最小值/最大值,是不是可以通过左右子树的最小值/最大值和root.val比较出来?
判断以root为根的二叉树是不是BST,是不是得先判断左右子树是不是BST?是不是还得看看左右子树左右子树的最大值和最小值?
如果当前节点要做的事情需要通过通过左右子树的计算结果推导出来,就要用到后序

以上是关于二叉树搜索子树的最大键值和的主要内容,如果未能解决你的问题,请参考以下文章

求二叉树中最大的二叉搜索子树的头节点

左神算法进阶班5_1求二叉树中最大搜索子树大小

L2-004 这是二叉搜索树吗?(二叉树)

二叉树进阶之寻找一棵二叉树中的最大二叉搜索子树

二叉搜索树基本操作实现

平衡二叉树插入操作的详细过程图解