题目描述:如果我们把二叉树看成图,定义“距离”为两节点之间的边的个数,写一个程序,求一棵二叉树中相距最远的两个节点之间的距离。
前几天在搜狗笔试的时候碰到了这个题目,其实原来一直在思考这个题目,但是一直没有想到好的实现方法,当时在考场上我是又急又恨啊,怎么就没有提前想明白呢?但是着急也没有用啊,还得静下心来搜肠刮肚来想。突然,灵机一动,计上心来,于是有了下面的解决方案。
//节点类
public class Node {
private int data;
private Node left;
private Node right;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public void setLeft(Node left) {
this.left = left;
}
public Node getRight() {
return right;
}
public void setRight(Node right) {
this.right = right;
}
public Node() {
super();
}
public Node(int data) {
super();
this.data = data;
}
}
这是树的节点类,为了插入方便,我使用的二叉排序树,其中包括了插入节点和通过遍历查找节点间的最大距离。
public class Tree {
public Node root;
private int maxLength;//记录最大距离
//插入新节点
public void insert(int data)
{
Node node=new Node(data);
if(root==null)
root=node;
else
{
Node current=root;
Node parrent=root;
boolean isLeft=false;
while(current!=null)
{
if(current.getData()>data)
{
parrent=current;
current=parrent.getLeft();
isLeft=true;
}
else
{
parrent=current;
current=parrent.getRight();
isLeft=false;
}
}
if(isLeft)
parrent.setLeft(node);
else
parrent.setRight(node);
}
}
//用中序遍历显示插入的数据
public void inorderTravel(Node node)
{
if(node!=null)
{
inorderTravel(node.getLeft());
int longLeft=depth(node.getLeft());//节点左子树的深度
int longRight=depth(node.getRight());//节点右子树的深度
//而以当前节点为根的子树的中的两个节点的最大距离就是longLeft+longRight
if(longLeft+longRight>maxLength)
maxLength=longLeft+longRight;
inorderTravel(node.getRight());
}
}
//计算树的深度
public int depth(Node node)
{
if(node==null)
return 0;
int a=depth(node.getLeft());
int b=depth(node.getRight());
return a>b?(a+1):(b+1);
}
public int getLength()
{
return maxLength;
}
}
下面是一个测试程序
public class TreeTest {
/**
* @param args
*/
public static void main(String[] args) {
Tree tree=new Tree();
tree.insert(10);
tree.insert(15);
tree.insert(27);
tree.insert(21);
tree.insert(38);
tree.insert(57);
tree.insert(9);
tree.insert(29);
tree.insert(30);
tree.insert(4);
tree.inorderTravel(tree.root);
System.out.println(tree.getLength());
}
}
返回值是7.
这个是通过计算子树的深度和来计算的,自认为不错,毕竟是理论上说得过去,而且实际上也是可行的。当然在后来一面的时候,面试官又让我描述了一下这个算法,我当时没有考虑那么多,麻烦了一些,还用一个链表通过前序遍历把所有非终端节点存储起来,再去一个个计算深度和。后来,面试官说,你不觉得很繁琐吗,有没有更简洁的算法,我当时摇了摇头。今天有机会实验一下,觉得算法还是不错的。转移了重点。对于这道题目,还有的说要父子节点之间是双向的,我觉得没有什么必要,也许是还有其他的更好的解决方法吧,希望大家批评指正。