环形链表追击问题

本文介绍了如何使用C语言判断链表是否存在环,并提供了解决基础版(仅判断环)和进阶版(找到环的入口点)的方法,通过快慢指针策略以及详细解释了为何这种方法有效。
摘要由CSDN通过智能技术生成

目录

题目描述

基础版本:

进阶版本:

实例

解决题目所需基础

解题思路

解题

1.手搓回环链表

2.判断链表是否有环

拓展问题:

3.寻找环形链表入口点

拓展问题:


题目描述

基础版本:

给你一个链表的头节点 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圈了,那是否还能通过头和交点的相遇找到回环入口???

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值