题目:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。
通用思路:
定义快慢指针 slow 和 fast,slow 一次走 1 步, fast 一次走 2 步。
遍历链表,直到 slow 和 fast 相遇停止。在相遇处定义一个指针 meet。
head 与 meet 同时移动,每次移动一步,直到两者相遇,停止移动。
根据公式推导,可得结论:head 与 meet 相遇处,即是入环口。
思路草图如下:
代码如下:
//核心代码段实现
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head;
struct ListNode* fast = head;
struct ListNode* meet = NULL;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//记录slow 与 fast 第一次相遇时的结点
meet = slow;
//再次遍历链表,直到 head 与 meet 相遇
while(head != meet)
{
head = head->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}
另一种思路:
在 slow 与 fast 第一次相遇时,记录下一个结点,并时相遇结点的 next 为空。即将找入环口的问题转化为 两链表相交,求交点的问题。
步骤可分为:
1、找快慢指针第一次相遇的结点
2、判断链表是否有环
3、如果有,则求两链表的长度,并比较两链表长度,计算其长度差,让长链表先走两者的距离步(即两链表长度差为多少,就先让那个长的链表先走多少步,之后两链表在一起移动,直到相遇,相遇代表结点一样)
4、找第一个相交点,即入环口。
代码如下:
//核心代码段:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head;
struct ListNode* fast = head;
struct ListNode* meet = NULL;
struct ListNode* newhead = NULL;
//用来判断是否有环,如果有,则flag会被改变
int flag = -1;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//找第一次相遇的结点
if(slow == fast)
{
meet = slow;
//将环断开,分为两段链表,通过两端链表找相交点,即入环口
newhead = meet->next;
meet->next = NULL;
flag = 1;
break;
}
}
//如果flag 没有被改变,则代表该链表无环
if(flag == -1)
return NULL;
struct ListNode* ogcur = head;
struct ListNode* newcur = newhead;
int oglen = 1;
int newlen = 1;
//求两链表长度
while(ogcur->next)
{
ogcur = ogcur->next;
oglen++;
}
while(newcur->next)
{
newcur = newcur->next;
newlen++;
}
//比较两链表长度
struct ListNode* shortList = head, *longList = newhead;
if(oglen > newlen)
{
shortList = newhead;
longList = head;
}
//长链表先走两者的距离步
int gap = fabs(oglen - newlen);
while(gap--)
{
longList = longList->next;
}
//找第一个相交点,即入环口
while(shortList != longList)
{
shortList = shortList->next;
longList = longList->next;
}
return shortList;
}
创作不易,希望看完的朋友们,如果对你们有帮助,给点支持!谢谢各位。
属于初学者,如果有哪里说的不好,欢迎各位大佬指点!