当前位置: 首页 > article >正文

【刷题】142. 环形链表 II

142. 环形链表 II

  • 一、题目描述
  • 二、示例
  • 三、实现
    • 3.1 方法1
    • 3.2 方法2


142. 环形链表 II

一、题目描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

二、示例

示例1:

在这里插入图片描述

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例2:

在这里插入图片描述

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例3:

在这里插入图片描述

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

三、实现

3.1 方法1

假设:

链表头到环入口点距离 = L
环入口点到相遇点距离 = X
环的长度 = C

slow走的路程: L + X L + X L+X

fast走的路程: L + n ∗ C + X L + n*C + X L+nC+X

由于fast速度是slow的两倍,则有等式: 2 ∗ ( L + X ) = L + n ∗ C + X 2*(L+X) = L + n * C + X 2(L+X)=L+nC+X
解得: L = n ∗ C − X = ( n − 1 ) ∗ C + C − X L = n*C - X = (n-1)*C + C-X L=nCX=(n1)C+CX

因此从链表头到环入口点距离( L = ( n − 1 ) ∗ C + C − X L = (n-1)*C + C-X L=(n1)C+CX)和从相遇点到环入口点距离( C − X C-X CX)相同,只是差了 ( n − 1 ) ∗ C (n-1)*C (n1)C 也就是 n − 1 n-1 n1 个环长。

由上可知,我们使用两个指针,一个指针从相遇点走,一个指针从链表头开始走,他们必定会在入口点相遇。

struct ListNode* detectCycle(struct ListNode* head) {
	struct ListNode* slow = head, * fast = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;

		// 带环 在环中相遇
		if (slow == fast)
		{
			struct ListNode* meet = slow;
			// 求入口点
			while (head != meet)
			{
				head = head->next;
				meet = meet->next;
			}

			return meet;
		}
	}

	return NULL;
}

3.2 方法2

快慢指针在环中相遇,把相遇点变成原链表的尾结点,相遇点的下一个结点变为新链表的头结点,这样求环的入口点问题,就变成了找两个链表的交点问题了。

但这会时间超时:参考代码 【求两个链表的交点-getIntersectionNode】

struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
	struct ListNode* tailA = headA;
	struct ListNode* tailB = headB;

	// 1.判断是否相交 通过查看两个链表的尾结点是否相同
	int lenA = 1, lenB = 1;
	while (tailA->next)
	{
		tailA = tailA->next;
		++lenA;
	}

	while (tailB->next)
	{
		tailB = tailB->next;
		++lenB;
	}

	if (tailA != tailB)
	{
		return NULL;
	}

	// 2.找交点,让长的链表先走 差距 步
	int gap = abs(lenA - lenB);
	struct ListNode* longList = headA;
	struct ListNode* shortList = headB;
	if (lenA < lenB)
	{
		longList = headB;
		shortList = headA;
	}

	while (gap--)
	{
		longList = longList->next;
	}

	while (longList != shortList)
	{
		longList = longList->next;
		shortList = shortList->next;
	}

	return longList;
}

struct ListNode* detectCycle(struct ListNode* head) {
	struct ListNode* slow = head, * fast = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;

		// 带环 在环中相遇
		if (slow == fast)
		{
			struct ListNode* meet = slow;
			
			return getIntersectionNode(head, meet->next);
		}
	}

	return NULL;
}


http://www.kler.cn/news/17997.html

相关文章:

  • maven配置阿里云镜像仓库
  • 关于C语言的一些笔记
  • 算法:递归启蒙-汉诺塔
  • ChatGPT使用入门
  • 计算机网络基础知识(一)计算机发展史、网络设备、网络结构及拓扑
  • 设计模式:SOLID原则
  • 2022级吉林大学面向对象第三次上机测试
  • 总结841
  • SSM框架学习-bean生命周期理解
  • new BroadcastChannel(),BroadcastChannel API使用介绍
  • 这就是实力~ 腾讯云大咖亲码 “redis深度笔记” 无废话全精华
  • 洗稿伪原创工具-洗稿生成器
  • SSM框架详解,实现高效优雅的Java Web开发
  • 【前端面经】CSS-浮动和清除浮动的方式
  • ePWM模块-时基模块(2)
  • Postgresql+Springboot yml基本使用
  • 通用操作日志处理方案
  • Vue如何使用富文本编辑器
  • PyTorch数据加载工具:高效处理常见数据集的利器
  • lombok常用的注解及使用方法
  • 实现前后端分离的登陆验证token思路
  • SpringBoot【开发实用篇】---- 配置高级
  • uniapp和小程序如何分包,详细步骤手把手(图解)
  • Java ——线程池
  • GitHub上的AutoGPT神秘的面纱
  • 100种思维模型之蝴蝶效应思维模型-56
  • 【QT】 QSS类的用法及基本语法介绍
  • 装饰器模式
  • 第三章 用户身份
  • 看Chat GPT解答《情报学基础教程》课后思考和习题