经典算法——链表中环的入口结点

题目:一个链表中包含环,如何找出环的入口结点?

例如,下图所示的链表中,环的入口结点就是结点3







完整测试程序:

#include <iostream>
using namespace std;

struct ListNode
{
	int   val;
	ListNode* next;
};

//利用一快一慢两个指针,快指针速度是慢指针的两倍,找到两个指针在环中的相遇点
ListNode* MeetingNode(ListNode* pHead)
{
	if (pHead == NULL)    return NULL;

	ListNode*  fast = pHead;
	ListNode*  slow = pHead;
	//如果无环,则fast先走到终点 ;当链表长度为奇数时,fast->Next为空 ;当链表长度为偶数时,fast为空  
	while( fast != NULL && fast->next != NULL)  
	{  
		fast = fast->next->next;  
		slow = slow->next;  
	     if(fast == slow) //如果有环,则fast会超过slow一圈再相遇
	     {  
			 return fast;
	      }  
	}
	return NULL;
}

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
	ListNode* meetingNode = MeetingNode(pHead);
	if (meetingNode == NULL)
		return NULL;

	// 求环中的节点个数
	int nodesInLoop = 1;
	ListNode* pNode1 = meetingNode;
	while (pNode1->next != meetingNode)
	{
		pNode1 = pNode1->next;
		++nodesInLoop;
	}

	// 结点指针pNode1先走nodesInLoop步
	pNode1 = pHead;
	for (int i = 0; i < nodesInLoop; ++i)
		pNode1 = pNode1->next;

	// 结点指针pNode1 和pNode2以相同的速度一起走
	ListNode* pNode2 = pHead;
	while (pNode1 != pNode2)
	{
		pNode1 = pNode1->next;
		pNode2 = pNode2->next;
	}
	return pNode1;
}

ListNode* CreateListNode(int value)
{
	ListNode* pNode = new ListNode();
	pNode->val= value;
	pNode->next = NULL;

	return pNode;
}

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

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

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

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

	ListNode* res = EntryNodeOfLoop(pNode1);
	cout << "链表中环的入口结点是:"<<res->val<<endl;
	system("pause");
	DestroyList(res);
	return 0;
}



ps:参考《剑指offer》中面试题56:链表中环的入口结点


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值