两个链表的第一个公共节点

/********************************************************************
题目:输入两个链表,找出它们的第一个公共节点。
********************************************************************/
/*
解题思路:
先遍历两个链表得到他们的长度,就能知道哪个链表较长,以及长的链表比短的
链表多几个节点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同
时在两个链表上遍历,找到第一个相同的节点就是他们的第一个公共节点。
*/
#include<stdio.h>
struct ListNode
{
	int m_nValue;
	ListNode* m_pNext;
};
int getListLength(ListNode* pHead);
ListNode* findFirstCommonNode(ListNode* pHead1, ListNode* pHead2)
{
	unsigned int nLength1 = getListLength(pHead1);
	unsigned int nLength2 = getListLength(pHead2);

	int nLengthDif = nLength1 - nLength2;
	ListNode* pLong = pHead1;
	ListNode* pShort = pHead2;
	
	if(nLength1 < nLength2)
	{
		pLong = pHead2;
		pShort = pHead1;
		nLengthDif = nLength2 - nLength1;
	}

	for(int i=0; i<nLengthDif; ++i)
		pLong = pLong->m_pNext;

	while((pLong != NULL) && (pShort != NULL) && (pLong != pShort))
	{
		pLong = pLong->m_pNext;
		pShort = pShort->m_pNext;
	}
	//得到第一个公共节点
	ListNode* pFirstCommonNode = pLong;

	return pFirstCommonNode;
}
int getListLength(ListNode* pHead)
{
	if(pHead == NULL)
		return 0;

	unsigned int nLength = 0;
	ListNode* pNode = pHead;
	while(pNode != NULL)
	{
		++nLength;
		pNode = pNode->m_pNext;
	}
	return nLength;
}
ListNode* createListNode(int value)
{
	ListNode* pNode = new ListNode();
	pNode->m_nValue = value;
	pNode->m_pNext = NULL;
	return pNode;
}
void connect(ListNode* pNode1, ListNode* pNode2)
{
	if(pNode1 == NULL || pNode2 == NULL)
		return;
	pNode1->m_pNext = pNode2;
}

void test()
{
	ListNode* pNode1 = createListNode(1);
	ListNode* pNode2 = createListNode(2);
	ListNode* pNode3 = createListNode(3);
	ListNode* pNode4 = createListNode(4);
	ListNode* pNode5 = createListNode(6);
	ListNode* pNode6 = createListNode(7);

	connect(pNode1,pNode2);
	connect(pNode2,pNode3);
	connect(pNode3,pNode4);
	connect(pNode4,pNode5);
	connect(pNode5,pNode6);

	ListNode* pNode11 = createListNode(4);
	ListNode* pNode12 = createListNode(5);


	connect(pNode11,pNode12);
	connect(pNode12,pNode5);
	connect(pNode5,pNode6);

	ListNode* pFirst = findFirstCommonNode(pNode1,pNode11);	
	if(pFirst != NULL)
		printf("%d\n",pFirst->m_nValue);
}
int main()
{
	test();
	return 0;
}

时间复杂度为O(M+N)



ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2)
{
	if(pHead1 == NULL || pHead2 == NULL)
		return NULL;

	int len1 = 0;
	int len2 = 0;
	
	ListNode* pNode = pHead1;
	while(pNode != NULL)
	{
		pNode = pNode->m_pNext;
		len1++;
	}

	pNode = pHead2;
	while(pNode != NULL)
	{
		pNode = pNode->m_pNext;
		len2++;
	}


	ListNode* pNode1 = pHead1;
	ListNode* pNode2 = pHead2;
	if(len2 > len1)
	{
		for(int i=0; i<len2-len1; ++i)
		{
			pNode2 = pNode2->m_pNext;
		}
	}
	else
	{
		for(int i=0; i<len1-len2; ++i)
		{
			pNode1 = pNode1->m_pNext;
		}
	}

	while(pNode1 != NULL && pNode2 != NULL)
	{
		if(pNode1 == pNode2)
			return pNode1;
		else
		{
			pNode1 = pNode1->m_pNext;
			pNode2 = pNode2->m_pNext;
		}
	}
	
	return NULL;
}


==参考剑指offer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值