何时使用后序遍历呢?
若是当前节点要作的事情须要经过左右子树的计算结果推导出来,就要用到后序遍历
二叉树相关题目最核心的的思路就是明确当前节点须要作的事情是什么???
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?是否是还得看看左右子树左右子树的最大值和最小值?
若是当前节点要作的事情须要经过经过左右子树的计算结果推导出来,就要用到后序this