二叉树中两个结点的距离

问题

对于普通的二叉树,如何找到两个给定节点之家的距离?距离是指连接两个节点需要的最小的边的条数。

例如下面的二叉树:

dist

 

这个问题很全面的考察了二叉树相关的知识,建议大家先尝试自己解决~

分析

假设给定的节点为node1, node2,可以分为下面两种情况:

1) node1是node2的祖先节点或孩子节点,可以理解为两个节点在一条线上。 例如:Dist(2,4), Dist(6,1)

2) node1 和 node2 没有直接或间接的父子关系。 例如,Dist(4,3), 他们需要一个共同的祖先节点1 连接起来。

关于两个节点的最低公共祖先(LCA)问题,可以参考:寻找二叉树两个节点的最低公共祖先

通过观察可以总结出下面的公式, lca是两个节点的最低公共祖先节点:

Dist(n1, n2) = Dist(root, n1) + Dist(root, n2) - 2*Dist(root, lca) 

 这个公式已经含盖了上面的两种情况。先找出lca,再求root节点到某个节点的距离就比较简单了。

下面是Java代码实现:

01 //============================================================================
02 // Name        : TreeNodesDistance.java
03 // Author      : GaoTong
04 // Date        : 2014/7/26
05 // Copyright   : www.acmerblog.com
06 //============================================================================
07  
08 class Node{
09     Node left,right;
10     int key;
11  
12     public Node(int i) {
13         this.key = i;
14     }
15 }
16  
17 public class TreeNodesDistance {
18  
19     //返回node节点在root中的第几层,-1表示没有在root子树下找到
20     public static int findLevel(Node root, int node){
21         if(root == nullreturn -1;
22         if(root.key == node) return 0;
23         //先在左子树查找
24         int level = findLevel(root.left, node);
25         //左子树没有找到则到右子树查找
26         if(level == -1){
27            level = findLevel(root.right, node);
28         }
29         if(level != -1)
30             return level+1;
31         return -1;
32     }
33  
34     public static Node findLCA(Node root, int node1,int node2){
35         if(root == nullreturn null;
36  
37         //找到两个节点中的一个就返回
38         if(root.key == node1 || root.key == node2){
39             return root;
40         }
41  
42         //分别在左右子树查找两个节点
43         Node left_lca = findLCA(root.left, node1, node2);
44         Node right_lca = findLCA(root.right, node1, node2);
45  
46         if(left_lca != null && right_lca != null){
47             //此时说明,两个节点肯定是分别在左右子树中,当前节点比为LCA
48             return root;
49         }
50         return left_lca != null ? left_lca : right_lca;
51     }
52  
53     public static int distanceNodes(Node root, int node1, int node2){
54         Node lca = findLCA(root, node1, node2);
55         int dis_lca = findLevel(root, lca.key);
56         int dis1 = findLevel(root, node1);
57         int dis2 = findLevel(root, node2);
58         return dis1 + dis2 - 2*dis_lca;
59     }
60  
61     public static void main(String args[]){
62         Node root = new Node(1);
63         root.left = new Node(2);
64         root.right = new Node(3);
65         root.left.left = new Node(4);
66         root.left.right = new Node(5);
67         root.right.left = new Node(6);
68         root.right.right = new Node(7);
69         root.right.left.right = new Node(8);
70  
71         System.out.println("Dist(8,7) = " + distanceNodes(root, 8,7));
72         System.out.println("Dist(8,3) = " + distanceNodes(root, 8,3));
73         System.out.println("Dist(8,3) = " + distanceNodes(root, 8,2));
74     }
75 }

时间复杂度为 O(N).

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值