目录
题目描述
基础版本:
给你一个链表的头节点
head
,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回
true
。 否则,返回false
。进阶版本:
给定一个链表的头节点
head
,返回链表开始入环的第一个节点。 如果链表无环,则返回null
。如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。如果pos
是-1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
实例
示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。
解决题目所需基础
C语言+链表+数理逻辑
解题思路
快慢指针:
(判断是否有环)定义三个结构体指针一个命名为fast作为快指针,一个命名为slow作为慢指针,另一个head指向头节点,初始fast和slow都指向链表头节点,fast一次向前走两步,slow一次向前走一步,若快指针与慢指针相遇,则说明链表有环,否则链表无环。
(寻找进入环的位置)再定义一个结构体指针node指向fast和slow相遇的位置,head和node每次向前走1步,二者相遇的位置即为进入环的位置
解题
1.手搓回环链表
#include <stdio.h>
#include <stdlib.h>
typedef int DataType
typedef struct ListNode
{
DataType val;
struct ListNode * next;
}List;
int main()
{
List * p1 = (List * )malloc(sizeof(List));
p1->val = 1;
List * p2 = (List * )malloc(sizeof(List));
p2->val = 2;
List * p3 = (List * )malloc(sizeof(List));
p3->val = 3;
List * p4 = (List * )malloc(sizeof(List));
p4->val = 4;
List * p5 = (List * )malloc(sizeof(List));
p5->val = 5;
List * p6 = (List * )malloc(sizeof(List));
p6->val = 6;
List * p7 = (List * )malloc(sizeof(List));
p7->val = 7;
p1->next = p2;
p2->next = p3;
ps->next = p4;
p4->next = p5;
p5->next = p6;
p6->next = p7;
p7->next = p4;
return 0;
}
2.判断链表是否有环
ListNode * AreThereCircle(ListNode* plist)
{
ListNode* fast = plist;
ListNode* slow = plist;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
return slow;
}
}
}
拓展问题:
为什么快链表一次走两步,慢链表一次走一步能追上?
fast指针先进入环,当slow指针进入环当中后,fast顺时针追赶slow指针,设fast指针与slow指针之间距离相距为L,则slow指针走L步后,fast指针追赶上slow指针
快链表一次走三步,慢链表一次走一步能否追上?
fast指针一次向前走3步,slow指针一次走1步,当fast指针与slow指针相距的L为偶数时,则fast指针第一次就能追上slow指针,当L为奇数时,fast指针在第一轮追不上slow指针,fast指针进入新一轮追击,fast指针与slow指针相距C-1(C为环长度),则在下一轮就能追上了。
为什么下一轮一定能追上???
已知L为奇数,讨论C的奇偶问题
slow指针:N fast指针:N+X*C+C-L
fast指针 = 3*slow指针
则:3N = N+X*C+C-L
则:2N = (X+1)*C-L
则:C比为奇数
则:C-1为偶数,下一轮一定能追上
3.寻找环形链表入口点
ListNode* DetectCycle(ListNode* phead)
{
ListNode* fast = phead;
ListNode* slow = phead;
ListNode* head = phead;
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if (slow == fast)
{
node = fast;
break;
//交点求出来了
}
}
//链表头处设置节点head,交点处设置node
//则head和node相遇时的位置就是回环链表的入口
while (node != head)
{
node = node->next;
head = head->next;
}
return node;
}
拓展问题:
若回环极小,则在slow指针进入环之前,fast指针已经在环内走了N圈了,那是否还能通过头和交点的相遇找到回环入口???