面试题37:两个链表的第一个公共结点

本文探讨如何解决找到两个链表第一个公共结点的问题。通过分析,提出让较长链表的指针先走,使得两链表长度相等后再同步移动,从而找到相同结点的方法。
摘要由CSDN通过智能技术生成
1.输入两个链表,找出他们的公共的结点
分析:

例如下面的两个链表,如果链表存在公共节点的话,则公共结点之后的所有结点都一样,两个链表的结尾结点是一样的。考虑到两个链表的长度不一样,如果两个指针分别同时指向链表的头节点,同时开始进行比较,这样显然不妥,因为如果两个链表存在公共结点的部分的话,则链表中存在后面一部分是重合的,这样的话可以先让长的链表的指针先走一定的长度,使得两个链表接下来比较的长度是一样的,这样每次两个链表的指针同时移动,如果存在公共的结点,则这两个指针的值就是相同的。


源码:

/**
		* 功能说明:
		* 作者:K0713
		* 日期:2016-9-8
		**/

#include<iostream>
using  namespace std;

struct ListNode
{
	int       m_nValue;
	ListNode* m_pNext;
};
//创建结点
ListNode* CreateListNode(int value);
//连接两个结点
void ConnectListNodes(ListNode* pCurrent, ListNode* pNext);
//打印结点的值
void PrintListNode(ListNode* pNode);
//打印链表中的所有结点
void PrintList(ListNode* pHead);
//释放整个链表
void DestroyList(ListNode* pHead);
//释放单个结点
void DestroyNode(ListNode* pNode);
//练笔尾部添加结点
void AddToTail(ListNode** pHead, int value);
//删除指定的值的结点
void RemoveNode(ListNode** pHead, int value);


ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2);
unsigned int GetListLength(ListNode* pHead);



int main()
{
	ListNode* pNode1 = CreateListNode(1);
	ListNode* pNode2 = CreateListNode(2);
	ListNode* pNode3 = CreateListNode(3);
	ListNode* pNode4 = CreateListNode(4);
	ListNode* pNode5 = CreateListNode(5);
	ListNode* pNode6 = CreateListNode(6);
	ListNode* pNode7 = CreateListNode(7);

	ConnectListNodes(pNode1, pNode2);
	ConnectListNodes(pNode2, pNode3);
	ConnectListNodes(pNode3, pNode6);
	ConnectListNodes(pNode4, pNode5);
	ConnectListNodes(pNode5, pNode6);
	ConnectListNodes(pNode6, pNode7);

	ListNode* resultNode = FindFirstCommonNode(pNode1, pNode4);
	PrintList(pNode1);
	PrintList(pNode4);
	cout << "the result is:" << endl;
	PrintListNode(resultNode);
	//DestroyList(pNode1);//有公共结点的情况下不能采用这种方法来释放结点,因为公共的部分会存在释放两边的危险,导致内存异常
	//DestroyList(pNode4);
	DestroyNode(pNode1);
	DestroyNode(pNode2);
	DestroyNode(pNode3);
	DestroyNode(pNode4);
	DestroyNode(pNode5);
	DestroyNode(pNode6);
	DestroyNode(pNode7);
	system("PAUSE");
	return 0;

}


ListNode* CreateListNode(int value)
{
	ListNode* pNode = new ListNode();
	pNode->m_nValue = value;
	pNode->m_pNext = NULL;

	return pNode;
}

void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
{
	if (pCurrent == NULL)
	{
		printf("Error to connect two nodes.\n");
		exit(1);
	}

	pCurrent->m_pNext = pNext;
}

void PrintListNode(ListNode* pNode)
{
	if (pNode == NULL)
	{
		cout<<"The node is NULL"<<endl;
	}
	else
	{
		cout << "The key in node is:" << pNode->m_nValue << endl;
	}
}

void PrintList(ListNode* pHead)
{
	cout << "PrintList starts." << endl;

	ListNode* pNode = pHead;
	while (pNode != NULL)
	{
		cout<<pNode->m_nValue<<"	";
		pNode = pNode->m_pNext;
	}
	cout << endl << "PrintList ends" << endl;
}

void DestroyList(ListNode* pHead)
{
	ListNode* pNode = pHead;
	while (pNode != NULL)
	{
		pHead = pHead->m_pNext;
		delete pNode;
		pNode = pHead;
	}
}

void DestroyNode(ListNode* pNode)
{
	delete pNode;
	pNode = NULL;
}
void AddToTail(ListNode** pHead, int value)
{
	ListNode* pNew = new ListNode();
	pNew->m_nValue = value;
	pNew->m_pNext = NULL;

	if (*pHead == NULL)
	{
		*pHead = pNew;
	}
	else
	{
		ListNode* pNode = *pHead;
		while (pNode->m_pNext != NULL)
			pNode = pNode->m_pNext;

		pNode->m_pNext = pNew;
	}
}

void RemoveNode(ListNode** pHead, int value)
{
	if (pHead == NULL || *pHead == NULL)
		return;

	ListNode* pToBeDeleted = NULL;
	if ((*pHead)->m_nValue == value)
	{
		pToBeDeleted = *pHead;
		*pHead = (*pHead)->m_pNext;
	}
	else
	{
		ListNode* pNode = *pHead;
		while (pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
			pNode = pNode->m_pNext;

		if (pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value)
		{
			pToBeDeleted = pNode->m_pNext;
			pNode->m_pNext = pNode->m_pNext->m_pNext;
		}
	}

	if (pToBeDeleted != NULL)
	{
		delete pToBeDeleted;
		pToBeDeleted = NULL;
	}
}

ListNode* FindFirstCommonNode(ListNode *pHead1, ListNode *pHead2)
{
	// 得到两个链表的长度
	unsigned int nLength1 = GetListLength(pHead1);
	unsigned int nLength2 = GetListLength(pHead2);
	int nLengthDif = nLength1 - nLength2;//默认第一个链表长

	ListNode* pListHeadLong = pHead1;
	ListNode* pListHeadShort = pHead2;
	if (nLength2 > nLength1)//如果第二个链表长,则更新
	{
		pListHeadLong = pHead2;
		pListHeadShort = pHead1;
		nLengthDif = nLength2 - nLength1;
	}

	// 先在长链表上走几步,再同时在两个链表上遍历
	for (int i = 0; i < nLengthDif; ++i)
		pListHeadLong = pListHeadLong->m_pNext;

	while ((pListHeadLong != NULL) &&
		(pListHeadShort != NULL) &&
		(pListHeadLong != pListHeadShort))
	{
		pListHeadLong = pListHeadLong->m_pNext;
		pListHeadShort = pListHeadShort->m_pNext;
	}

	// 得到第一个公共结点
	ListNode* pFisrtCommonNode = pListHeadLong;

	return pFisrtCommonNode;
}

unsigned int GetListLength(ListNode* pHead)
{
	unsigned int nLength = 0;
	ListNode* pNode = pHead;
	while (pNode != NULL)
	{
		++nLength;
		pNode = pNode->m_pNext;
	}

	return nLength;
}
结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值