【14】最近公共祖先问题

题目:给定一颗二叉树的两个结点,求这两个结点的最近公共祖先结点

分析:1. 假如二叉树是二叉排序树

               根据二叉排序树的性质,左子树结点的值小于根结点,根结点的值小于右子树结点的值

               那么每次只要判断,给定的两个结点的值和左右结点的值比较即可

               如果两个值都小于根结点的值,则递归到左子树

               如果两个值都大于根结点的值,则递归到右子树

               否则根结点即为最近公共祖先

            2. 如果二叉树不是排序二叉树,那么二叉树如果有一个指向父节点的指针,则题目变成求”给定两个结点,从两个结点到根结点这两条路径的第一个公共结点“和链表求公共结点一样

下面给出两种情况的代码

1. 二叉树是排序二叉树

//二叉树结点
struct BinaryTreeNode{
    int value;
	BinaryTreeNode *lsonNode;
	BinaryTreeNode *rsonNode;
};

//二叉排序树找最近公共祖先
BinaryTreeNode* FindCommonNode(BinaryTreeNode *root
	, BinaryTreeNode *nodeOne, BinaryTreeNode *nodeTwo){

	if(root == NULL || nodeOne == NULL || nodeTwo == NULL){
	   return NULL;
	}
	if((root->value > nodeOne->value)
		&& (root->value > nodeTwo->value)){ //递归到左子树
		return FindCommonNode(root->lsonNode, nodeOne, nodeTwo);
	}
	else if((root->value < nodeOne->value)
		&& (root->value < nodeTwo->value)){ //递归到右子树
			return FindCommonNode(root->rsonNode, nodeOne, nodeTwo);
	}
	else{ //当前点即为最近公共祖先
	    return root;
	}
}

2. 二叉树不是排序二叉树但是又指向父节点的指针

//二叉树的结点
struct BinaryTreeNode{
    int value;
	BinaryTreeNode *lsonNode;
	BinaryTreeNode *rsonNode;
	BinaryTreeNode *fatherNode;
};

//找最近公共祖先
BinaryTreeNode* FindCommonNode(BinaryTreeNode *root,
	BinaryTreeNode *nodeOne, BinaryTreeNode *nodeTwo){
	if(root == NULL || nodeOne == NULL || nodeTwo == NULL){
	    return NULL;
	}
	//求出两个结点到根结点root的长度
	int lenNodeOne = 0;
	int lenNodeTwo = 0;

	BinaryTreeNode *tmpNode = nodeOne;
	while(tmpNode != NULL){
	    ++lenNodeOne;
		tmpNode = tmpNode->fatherNode;
	}
	tmpNode = nodeTwo;
	while(tmpNode != NULL){
	    ++lenNodeTwo;
		tmpNode = tmpNode->fatherNode;
	}
	//让长的链先走几步
	BinaryTreeNode *pNodeOne = nodeOne;
	BinaryTreeNode *pNodeTwo = nodeTwo;
	if(lenNodeOne > lenNodeTwo){
		while(lenNodeOne > lenNodeTwo){
		     --lenNodeOne;
			 pNodeOne = pNodeOne->fatherNode;
		}
	}
	else{
	    while(lenNodeOne < lenNodeTwo){
		     --lenNodeTwo;
			 pNodeTwo = pNodeTwo->fatherNode;
		}
	}
	//两个指针一起走
	while((pNodeOne != pNodeTwo) && (pNodeOne != NULL) && (pNodeTwo != NULL)){
		pNodeOne = pNodeOne->fatherNode;
		pNodeTwo = pNodeTwo->fatherNode;
	}
	//如果两个相等说明有公共结点
	if(pNodeOne == pNodeTwo){
	    return pNodeOne;
	}
	else{
	    return NULL;
	}
}
时间: 2024-11-03 21:55:59

【14】最近公共祖先问题的相关文章

[算法系列之三十一]最近公共祖先(LCA)

[简介] 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点. 例如,对于下面的树,结点4和结点6的最近公共祖先LCA(T,4,6)为结点2. 求树中两个结点的最低公共祖先是面试中经常出现的一个问题.一般的做法,可能是针对是否为二叉查找树分情况讨论. LCA问题的扩展主要在于结点是否只包含父结点指针,对于同一棵树是否进行多次LCA查询

求树中两个结点的最近公共祖先

剑指offer上的最后一题了,一个递归函数调了一下午,才得到正确的结果. 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数. 其中每个测试样例包括两行,第一行为一个二叉树的先序遍历序列,其中左右子树若为空则用0代替,其中二叉树的结点个数node_num<10000. 第二行为树中的两个结点的值m1与m2(0<m1,m2<10000). 输

使用C语言求二叉树结点的最低公共祖先的方法_C 语言

算法分析 我们直接来分析O(n)的算法. 比如求节点F和节点H的最低公共祖先,先求出从根节点A到F的路径,再求出A到H的路径,那么最后一个相同的节点就是最低公共祖先.A->B->D->F和A->B->E->H,最后相同的节点事B,所以最低公共祖先是B节点.求根节点到指定节点的算法先前已经更新过了,复杂度是O(n),所以总的时间复杂度是O(n). 条件细化: (1)树如果是二叉树,而且是二叉排序树.              这中条件下可以使用二叉排序树的搜索功能找到最低

数据结构算法-关于求二叉树的最低公共结点

问题描述 关于求二叉树的最低公共结点 源代码: int hasnode(bitree tchar c){ if(!t) return 0; else if(t->data==c) return 1; return (hasnode(t->lchildc)||hasnode(t->rchildc));} bitree commonfather(bitree tchar c1char c2){ if(hasnode(tc1)==0||hasnode(tc2)==0) return 0; wh

语言-试编写算法,求二叉树T中结点a和b的最近共同祖先。

问题描述 试编写算法,求二叉树T中结点a和b的最近共同祖先. 试编写算法,求二叉树T中结点a和b的最近共同祖先.二叉链表类型定义:typedef struct BiTNode { TElemType data; struct BiTNode lchild*rchild;} BiTNode *BiTree;可用栈类型Stack的相关定义:typedef struct { BiTNode *ptr; // 二叉树结点的指针类型 int tag; // 0..1} SElemType; // 栈的元素

POJ题目分类

初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      (4)递推.      (5)构造法.(poj3295)      (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法:      (1)图的深度优先遍历和广度优先遍历.      (2)最短路径算法(dijkstra,bellman-ford

poj 1330 Nearest Common Ancestors:LCA入门题

链接: http://poj.org/problem?id=1330 题目: Nearest Common Ancestors Time Limit: 1000MS     Memory Limit: 10000K Total Submissions: 12678     Accepted: 6764 Description A rooted tree is a well-known data structure in computer science and engineering. An e

管道和FIFO

管道(pipe)       管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道是典型的单向通信,即计算机网络中所说的"半双工".管道又名匿名管道,所以只能用在具有公共祖先的进程之间使用,通常使用在父子进程之间通信.通常是父进程创建一个管道,然后fork一个子进程,此后父子进程共享这个管道进行通信. 管道由pipe函数创建,函数原型如下:       #include<unistd

poj分类

初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.      (4)递推.      (5)构造法.(poj3295)      (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996) 二.图算法:      (1)图的深度优先遍历和广度优先遍历.      (2)最短路径算法(dijkstra,bellman-ford