二叉树9:树上最远距离练习题

来源:互联网 发布:性冲动 知乎 编辑:程序博客网 时间:2024/05/17 05:59

题目:从二叉树的节点A出发,可以向上或者向下走,但沿途的节点只能经过一次,当到达节点B时,路径上的节点数叫作A到B的距离。对于给定的一棵二叉树,求整棵树上节点间的最大距离。给定一个二叉树的头结点root,请返回最大距离。保证点数大于等于2小于等于500.

思路:理解题目的含义,对于一棵以root为根的二叉树,树上的最大距离可能来自3中情况:

情况1:完全来自root的左子树,如图所示,即最大路径不经过root结点,只在结点1的左子树2上面,此时的最大距离为8。

情况2:完全来自root结点的右子树,如图所示,最大路径不经过root结点,只在结点1的右侧左子树3上面,此时最大距离是9。

情况3:来自结点root的两侧,如图所示,经过root结点,此时的最大距离=root的左子树的高度(即结点3的最长路径)+root右子树的高度(即结点3的最长路径)+root结点本身。

分析可知,要计算结点root所在子树的最长距离,需要已知:左子树②的最长距离LMaxLength,左子树的高度LHeight;右子树③的最长距离RMaxLength,右子树的高度RHeight.然后比较Math.max(LMax,RMax,(LHeight+RHeight+1)),其最大值就是这棵二叉树的最大距离,即对于每个子树,需要求出它的最大距离和最大高度。显然这就是一个递推关系式,可以使用递归来实现,即设计一个递归函数,给定一个根结点root,求出这个根结点的最大距离max和最大高度height并返回这2个数值。其中maxLength= Math.max(LMax,RMax,(LHeight+RHeight+1));而由于要返回这棵子树的高度,如何求子树的高度呢?二叉树的高度就是它的2个子树高度中的较大值再加上1,即height=Math.max(LHeight, RHeight)+1;

递归的递推关系有了,关键是找到递归的起始条件或者理解为终止条件。这里使用的思想是后序遍历(先遍历左右子树再处理结论),联系二叉树的后序遍历算法,进行改编。显然if(root==null)时:max=0;height=0;

总结:设计一个递归函数,输入根结点root,求出这棵二叉树的最大距离maxLength和高度length并返回。递推关系为:

maxLength= Math.max(LMax,RMax,(LHeight+RHeight+1));

height=Math.max(LHeight, RHeight)+1

边界条件为:

if(root==null) return max=0;height=0;

在Java中不能分开返回2个值,因此要将2个值整合成为一个数组进行返回即可。

import java.util.*;//求二叉树上结点的最大距离:递归;最大值只可能来自3中情况public class LongestDistance {    public int findLongest(TreeNode root) {        //特殊输入        if(root==null) return 0;        //调用递归函数来求得最大距离maxLength和高度height        int[] results=this.process(root);        //返回结果        return results[0];    }        //这是一个递归方法,用于求出一个二叉树的最大距离和高度并返回这2个值    private int[] process(TreeNode root){         int[] tempResults=new int[2];        //边界条件        if(root==null){            tempResults[0]=0;            tempResults[1]=0;            return tempResults;        }                //最大值来自3中情况,进行比较        //左子树的结果:        int[] paramLeft=this.process(root.left);        int LMaxLength=paramLeft[0];        int LHeight=paramLeft[1];                //右子树的结果:        int[] paramRight=this.process(root.right);        int RMaxLength=paramRight[0];        int RHeight=paramRight[1];                //比较得到最大值和高度,并组成数组返回,常识:Math.max()函数只能比较2个数的大小        //递归的递推关系        tempResults[0]=Math.max(Math.max(LMaxLength,RMaxLength),LHeight+RHeight+1);        tempResults[1]=Math.max(LHeight,RHeight)+1;                //带有返回值的递归函数        return tempResults;    }}

常识:Math.max()函数只能放入2个参数,即只能比较2个数的大小,如果需要比较更多数的大小,那么在Math.max()里面再套用Math.max()即可。

对于递归方法,可以有返回值也可以没有返回值,并不影响递归的使用,递归的设计应该从功能上来思考,思考这个递归方法需要解决一个什么问题?需要输入的信息是什么?返回的信息又是什么?在这个递归方法中需要对下一层递归方法的返回值进行怎样的处理?(即如何递推);从策略上来讲,就是先明确递推关系再明确初始条件(终止条件)。


0 0
原创粉丝点击