二叉树公共祖先问题
1. 问题描述1:
有如下图的二叉树:
------------------1---------------------
-------------/---------\-----------------
--------2-----------------3-------------
-----/------\------------/-----\---------
---4---------5--------6---------7------
-/---\------/---\-----/---\------/---\---
-8----9---10---11--12--13---14---15-
两条到根节点的路径,例如:(4, 2, 1)和(11,5,2,1),从2处开始相交。
现给定起始点x和y,求第一个相交点。
思路:
1. 子节点与父节点的关系:children/2 = parent
2. 递归:给定初始点,如果两者不同,则大的除以2(往上遍历路径),递归后直到第一个相交处即使所求解。
代码:
1 int first_cross(int x, int y) 2 { 3 if( x == y ) return x; 4 else if( x > y ) return first_cross(x/2, y); 5 else return first_cross(x, y/2); 6 }
2. 问题描述2:
二叉树是一颗二叉查找树,即左边小于当前,右边大于当前。
思路:
1. 利用查找树的性质以及最近公共祖先的特性(最近公共祖先一定将两个节点分隔在左右两边),所以可以从根节点开始往下递归
2. 判断两节点是否在当前节点的左右两侧,如果不是继续递归,直到是则找到了要求的节点
代码:
1 //n1->data <= n2->data 2 BNode_t* firstCommonAncestor(BNode_t* cur, BNode_t* n1, BNode_t* n2) 3 { 4 if( cur == NULL ) 5 { 6 return NULL; 7 } 8 if( n1->data <= cur->data && n2->data >= cur->data) 9 { 10 return cur; 11 } 12 if( n1->data <= cur->data ) 13 { 14 return firstCommonAncestor(cur->left, n1, n2); 15 } 16 return firstCommonAncestor(cur->right, n1, n2); 17 } 18 19 BNode_t* solution() 20 { 21 if( node1->data <= node2->data ) 22 return firstCommonAncestor(root, node1, node2); 23 return firstCommonAncestor(root, node2, node1); 24 }
3. 问题描述3:
如果节点内容是随机存放的,给定两个节点的指针,如何找到最近的公共祖先?
第一种情况没有指向父节点的指针。
第二种情况存在指向父节点的指针。
思路(第一种情况):
1. 最近公共祖先意味着两个节点是该祖先的孩子节点,并且是第一个
2. 用递归求解思路非常简便,从根开始判断是否包括这两个子节点,一直往下,直到找到为止
代码:
1 BNode_t* firstCommonAncestor(BNode_t* cur, BNode_t* n1, BNode_t* n2) 2 { 3 if( cur == NULL ) 4 { 5 return NULL; 6 } 7 if( n1 == NULL && n2 == NULL ) 8 { 9 return NULL; 10 } 11 if( cur->left == n1 || cur->right == n1 ) 12 { 13 n1 = NULL; 14 } 15 if( cur->left == n2 || cur->right == n2 ) 16 { 17 n2 = NULL; 18 } 19 BNode_t* left = firstCommonAncestor(cur->left, n1, n2); 20 if( left != NULL ) 21 { 22 return left; 23 } 24 BNode_t* right = firstCommonAncestor(cur->right, n1, n2); 25 if( right != NULL ) 26 { 27 return right; 28 } 29 return cur; 30 }
思路(第二种情况,有父节点):
这种情况下又可以变形,比如节点内可以得到当前高度,这样就可以做类似本文最开始的递归操作。
1. 先遍历一个节点的父节点,一直往上直到根节点,并用set存储路径上的节点O(h)空间和时间
2. 再遍历另一个节点的父节点,直到遇到set中已有的节点,则该节点就是要找的公共节点
代码:略
转载请注明引用自:
http://www.cnblogs.com/breakthings/p/4061762.html