每天一道算法题(19)——最近公共父节点问题

题目:     

     给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数原型:

strucy TreeNode{
     TreeNode* left;   //指向左子树
     TreeNode* right;   //指向右子树
     TreeNode* father;   //指向父亲节点
};
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
}

方法1

     算法复杂度为O(n)。

     先查找高度。然后类似于查找两条链表第一个公共节点的方法进行遍历比较:

int getHeight(TreeNode *node) {
    int height = 0;
    while (node) {
        height++;
        node = node->parent;
    }
    return height;
}
 
TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second) {
    int height1 = getHeight(first), height2 = getHeight(second), diff = height1 - height2;
    if (diff < 0) {
        diff = -diff;
        while(diff--) {
             second = second->parent;
        }
    } else {
        while(diff--) {
            first = first->parent;
        }
    }
    while (first != second) {//同步遍历
        first = first->parent;
        second = second->parent;
    }
    return first;
}


方法2:

    使用辅助存储空间。两个栈依次压入从该节点到根节点的指针。依次弹出栈比较节点。。

TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
	if(!first||!second)
		return;
	if(first==second)
		return first;

	stack<node> s1;
	stack<node> s2;
	node t1,t2;

	while(!first){
		s1.push(first);
		first=first->father;
	}
	while(!second){
		s2.push(second);
		first=first->father;
	}
	while(!s1.empty()&&!s2.empty()){
                t1=s1.top();s1.pop();
		t2=s2.top();s2.pop();

		if(t1!=t2)
			return NULL;
		else if((t1==t2)&&!s1.empty()&&!s2.empty()&&(s1.top()!=s2.top()))//当前节点相等,下一级不相等
			return t1;
		else if((t1==t2)&&(s1.empty()||s2.empty()))//当前节点相等,下一级为空
			return t1;
	}	
	return NULL;
}


引申:

      考虑特殊情况,即二叉树为二叉查找数的情况:

TreeNode* LowestCommonAncestor(TreeNode* head,TreeNode* first,TreeNode* second){
	if(!first||!second)
		return;
	if(first==second)
		return first;

	if(first->value>second->value){
		TreeNode* t;
		t=first;
		first=second;
		second=first;
	}

	if(first->value>head->value)
		return LowestCommonAncestor(head->right,first,second);
	else if(second->value<head->value)
		return LowestCommonAncestor(head->left,first,second);
	else
		return head;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值