题目
如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义”距离”为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离;
实现
分析
计算一个二叉树的最大距离有两个情况:
情况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;
}
}