微软面试100题系列---求二叉树中节点的最大距离

题目

如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义”距离”为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离;
这里写图片描述

实现

分析

计算一个二叉树的最大距离有两个情况:

  • 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。

  • 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。

这里写图片描述

只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离。

方法1

思路:二叉树的操作一般都是递归实现的,此时也采用递归思想。
对于以node节点为根节点的树,首先求左子树距根的最大距离maxLeft;然后求右子树距根的最大距离maxRight;则以node为根的二叉树中节点最大距离为=maxLeft+maxRight;
对于每个节点,都记录了左子树到该节点的最大距离,右子树到该节点的最大距离;

代码:


public class Num11 {

    public static int maxLen=0;
    public static void main(String[] args) {
        Node root_1=createTree_1();
        Node root_2=createTree_2();
/*
        FindMaxDistance(root_1);
        System.out.println(maxLen);

        maxLen=0;*/
        FindMaxDistance(root_2);
        System.out.println(maxLen);
    }

    public static Node createTree_1(){
        Node root=new Node(1);
        Node node=new Node(2);
        root.left=node;
        node=new Node(3);
        root.right=node;

        node=new Node(4);
        root.left.left=node;
        root.left.right=new Node(5);

        root.right.left=new Node(6);
        root.right.right=new Node(7);

        root.left.left.left=new Node(8);
        root.right.right.left=new Node(9);

        return root;
    }

    public static Node createTree_2(){
        Node root=new Node(1);

        Node node=new Node(2);
        root.left=node;

        node=new Node(3);
        root.left.left=node;
        root.left.right=new Node(5);

        root.left.left.left=new Node(4);
        root.left.right.right=new Node(6);

        return root;
    }

    public static void FindMaxDistance(Node root){
        if(root==null){
            return;
        }
        if(root.left==null){
            root.leftMaxDistance=0;
        }
        if(root.right==null){
            root.rightMaxDistance=0;
        }
        if(root.left!=null){
            FindMaxDistance(root.left);
        }
        if(root.right!=null){
            FindMaxDistance(root.right);
        }
        if(root.left!=null){
            root.leftMaxDistance=max(root.left.leftMaxDistance,root.left.rightMaxDistance)+1;
        }
        if(root.right!=null){
            root.rightMaxDistance=max(root.right.leftMaxDistance,root.right.rightMaxDistance)+1;
        }
        if(root.leftMaxDistance+root.rightMaxDistance>maxLen){
            maxLen=root.leftMaxDistance+root.rightMaxDistance;
        }
    }

    private static int max(int a, int b) {
        return a>b?a:b;
    }

}

class Node{
    int value;
    Node left;
    Node right;
    int leftMaxDistance;
    int rightMaxDistance;

    public Node(int value){
        this.value=value;
        this.left=null;
        this.right=null;
    }
}

方法2

这个问题的核心是,情况A 及 B 需要不同的信息: A 需要子树的最大深度,B 需要子树的最大距离。只要函数能在一个节点同时计算及传回这两个信息(将这2类消息封装到一个类中);


public class Num11_2 {

    public static void main(String[] args) {
        Node_2 root_1=createTree_1();
        Result res_1=FindMaxDistance(root_1);
        System.out.println(res_1.maxDistance+"   "+res_1.maxDepth);

        Node_2 root_2=createTree_2();
        Result res_2=FindMaxDistance(root_2);
        System.out.println(res_2.maxDistance+"   "+res_2.maxDepth);     
    }


    public static Node_2 createTree_1(){
        Node_2 root=new Node_2(1);
        Node_2 node=new Node_2(2);
        root.left=node;
        node=new Node_2(3);
        root.right=node;

        node=new Node_2(4);
        root.left.left=node;
        root.left.right=new Node_2(5);

        root.right.left=new Node_2(6);
        root.right.right=new Node_2(7);

        root.left.left.left=new Node_2(8);
        root.right.right.left=new Node_2(9);

        return root;
    }

    public static Node_2 createTree_2(){
        Node_2 root=new Node_2(1);

        Node_2 node=new Node_2(2);
        root.left=node;

        node=new Node_2(3);
        root.left.left=node;
        root.left.right=new Node_2(5);

        root.left.left.left=new Node_2(4);
        root.left.right.right=new Node_2(6);

        return root;
    }

    public static Result FindMaxDistance(Node_2 root){
        if(root==null){
            return new Result(-1,0);
        }

        Result lhs=FindMaxDistance(root.left);
        Result rhs=FindMaxDistance(root.right);

        Result res=new Result();
        res.maxDepth=max(lhs.maxDepth+1,rhs.maxDepth+1);
        res.maxDistance=max(max(lhs.maxDistance,rhs.maxDistance),lhs.maxDepth+rhs.maxDepth+2);

        return res;
    }

    private static int max(int i, int j) {
        return i>j?i:j;
    }

}
class Node_2{
    int value;
    Node_2 left;
    Node_2 right;

    public Node_2(int value){
        this.value=value;
        this.left=null;
        this.right=null;
    }
}

class Result{
    int maxDepth;
    int maxDistance;

    public Result(){

    }

    public Result(int maxDepth,int maxDistance){
        this.maxDepth=maxDepth;
        this.maxDistance=maxDistance;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值