剑指offer之面试题50树中两个结点的最低公共祖先

问题描述

设计一个算法,找出给定的任意两个结点的公共父结点。

实现代码如下:

方法一、用链表记录遍历的路径,而后比较两个链表。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
struct TreeNode{
	int value;
	struct TreeNode *left;
	struct TreeNode *right;
};
typedef struct TreeNode Node;

struct List{
	Node *value;
	struct List *next;
};
typedef struct List List;

bool doFindCommonNode(Node *node,int num,List *listNum){
	if(node==NULL)return false;
	if(node->value==num){
		return true;
	}
	bool rs =false;
	List *temp =(List *)malloc(sizeof(List));
	temp->value=node;
	temp->next=listNum->next;
	listNum->next=temp;
	rs = doFindCommonNode(node->left,num,listNum);
	if(!rs)
		rs = doFindCommonNode(node->right,num,listNum);
	if(!rs){
		listNum->next=temp->next;
		free(temp);
	}
	return rs;
}

Node *findCommonNode(Node *head,int num1,int num2){
	Node *rs=NULL;
	List *listNum1 =(List *)malloc(sizeof(List));
	List *listNum2 =(List *)malloc(sizeof(List));
	
	listNum1->next=NULL;
	listNum2->next=NULL;
	bool b1,b2;
	if(head!=NULL){
		b1 = doFindCommonNode(head,num1,listNum1);
		if(num1==num2){
			if(listNum1->next==NULL)
				return NULL;
			else
				return listNum1->next->value;
		}
		b2 = doFindCommonNode(head,num2,listNum2);
		if(b1 && b2){
			List *longlist=listNum1->next;
			List *shortlist=listNum2->next;
			List *head1=listNum1->next;
			List *head2=listNum2->next;
			int count1=0,count2=0;
			
			while(head1!=NULL){
				count1++;
				head1=head1->next;
			}
			
			while(head2!=NULL){
				count2++;
				head2=head2->next;
			}
			
			int dis=count1-count2;
			if(count1<count2){
				List *temp = longlist;
				longlist=shortlist;
				shortlist=temp;
				dis=count2-count1;
			}
			
			int i=0;
			for(i=0;i<dis;i++)
				longlist=longlist->next;
			
			while(shortlist!=NULL && longlist!=NULL && longlist->value!=shortlist->value){
				longlist=longlist->next;
				shortlist=shortlist->next;
			}
			if(longlist!=NULL && shortlist!=NULL){
				rs=longlist->value;
			}
		}
	}
	return rs;
}

int main(int argc, char *argv[])
{
	Node *head=(Node *)malloc(sizeof(Node));
	head->value=0;
	head->right=NULL;
	head->left=(Node *)malloc(sizeof(Node));
	head->left->value=1;
	head->left->left=(Node *)malloc(sizeof(Node));
	head->left->left->value=2;
	head->left->left->left=NULL;
	head->left->left->right=NULL;
	head->left->right=(Node *)malloc(sizeof(Node));
	head->left->right->value=3;
	head->left->right->left=NULL;
	head->left->right->right=NULL;
	int num1,num2;
	scanf("%d %d",&num1,&num2);
	Node *rs = findCommonNode(head,num1,num2);
	if(rs!=NULL)
		printf("the common node is :%d\n",rs->value);
	else
		printf("there is no comomn Node!\n");
	return 0;
}

方法二
、直接判断两个结点是否在当前结点的左右两侧,如在,则该结点就是所求。否则继续遍历。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
struct TreeNode{
	int value;
	struct TreeNode *left;
	struct TreeNode *right;
};
typedef struct TreeNode Node;

bool isfind = false;

bool doFindCommonNode(Node *node,Node **rs,int num1,int num2){
	if(isfind || node==NULL)return false;
	if(node->value==num1){
		return true;
	}
	if(node->value==num2){
		return true;
	}
	bool left = doFindCommonNode(node->left,rs,num1,num2);
	bool right = doFindCommonNode(node->right,rs,num1,num2);
	if(num1==num2 && (left==true || right==true)){
		isfind=true;
		*rs=node;
		return true;
	}
	if(left==true && right==true){
		isfind=true;
		*rs=node;
		return true;
	}else if(left==true || right==true){
		return true;
	}else{
		return false;
	}
}

Node *findCommonNode(Node *head,int num1,int num2){
	Node **rs =(Node **)malloc(sizeof(Node *));
	*rs=NULL;
	if(head!=NULL){
		if(doFindCommonNode(head,rs,num1,num2) && isfind){
			printf("find the Node!\n");
		}else{
			printf("there is no comomn Node!\n");
		}
	}
	return *rs;
}

int main(int argc, char *argv[])
{
	Node *head=(Node *)malloc(sizeof(Node));
	head->value=0;
	head->right=NULL;
	head->left=(Node *)malloc(sizeof(Node));
	head->left->value=1;
	head->left->left=(Node *)malloc(sizeof(Node));
	head->left->left->value=2;
	head->left->left->left=NULL;
	head->left->left->right=NULL;
	head->left->right=(Node *)malloc(sizeof(Node));
	head->left->right->value=3;
	head->left->right->left=NULL;
	head->left->right->right=NULL;
	int num1,num2;
	scanf("%d %d",&num1,&num2);
	Node *rs = findCommonNode(head,num1,num2);
	if(rs!=NULL)
		printf("the common node is :%d\n",rs->value);
	return 0;
}

参考资料
剑指offer

备注
转载请注明出处:http://blog.csdn.net/wsyw126/article/details/51386597
作者:WSYW126

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值