首页 > 其他分享 >LeetCode热题100(二十六) —— 142.环形链表II

LeetCode热题100(二十六) —— 142.环形链表II

时间:2025-01-11 18:04:21浏览次数:3  
标签:node 142 next 链表 节点 ListNode 热题 指针

LeetCode热题100(二十六) —— 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
        解释:链表中没有环。

在这里插入图片描述

提示:
        链表中节点的数目范围在范围 [0, 104] 内
        -105 <= Node.val <= 105
        pos 的值为 -1 或者链表中的一个有效索引
        
进阶:你是否可以使用 O(1) 空间解决此题?

代码实现

  • 思路一:哈希表
public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        ListNode node = head;
        while (node != null) {
            if (set.contains(node)) {
                return node;
            } else {
                set.add(node);
            }
            node = node.next;
        }
        return null;
    }
}
  • 思路二:快慢指针
public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast == slow) {
                ListNode node = head;
                while (node != slow) {
                    node = node.next;
                    slow = slow.next;
                }
                return node;
            }
        }
        return null;
    }
}
  • 数据结构
class ListNode {
	int val;
	ListNode next;
	ListNode(int x) {
		val = x;
		next = null;
	}
}

思路解析

  1. 输入:链表头节点 ListNode head
  2. 输出:链表成环节点 ListNode cycleNode 无环则返回 null
  3. 思路一:哈希表 HashSet
    • 关键:尾节点的 next 指向
      • 无环,next == null
      • 有环,next -> node 链表中某个节点
      • 有环,遍历链表,当某个节点被第二次访问到时,它就是尾节点的next
    • 时间复杂度: O ( n ) O(n) O(n)
    • 空间复杂度: O ( n ) O(n) O(n)
  4. 思路二:快慢指针
    • 慢指针slow一次移动1个位置,快指针fast一次移动2个位置
      • 无环,fast 指针将先走到尾节点或尾节点的前一个节点,其后 next == null
      • 有环,快指针将追上慢指针,二者相遇
    • 关键节点:入环节点 C & 相遇节点 M
    • 关键思路:快慢指针相遇后到入环节点的距离等于头节点到入环节点的距离

在这里插入图片描述

  • 推理逻辑:
    • 设定参数
      • L :头节点到入环节点的距离
      • T :入环节点到相遇节点的距离
      • R :相遇节点到入环节点的距离
    • 当快慢指针相遇时
      • 慢指针移动距离:L + T
      • 快指针移动距离:L + q * (T + R) + T
        • 其中 q*(T+R)代表快指针先经过入环节点并已走完 q(q = 1,2,3,...)
      • 同时,快指针移动距离 = 慢指针的两倍,即 L + q * (T + R) + T = 2 * (L + T)
      • 化简公式:(q - 1) * (T + R) + R = L 可推理出 R = L
      • 等式左侧:从相遇节点 M 起走到入环节点 C (经过 q-1圈)
      • 等式右侧:从头节点 head 起走到入环节点 C
  • 时间复杂度: O ( n ) O(n) O(n) = O ( n ) + O ( n ) O(n)+O(n) O(n)+O(n)
    • 虽然是双循环嵌套,但满足条件的内层循环只执行1次
    • 外层循环寻找相遇节点,慢指针移动不超过 n 次,寻找过程不触发内层循环执行
    • 内层循环寻找入环节点,指针移动不超过 n 次,相遇后内层循环执行完直接return
  • 空间复杂度: O ( 1 ) O(1) O(1) 只用了3个指针
  1. 相关知识点

标签:node,142,next,链表,节点,ListNode,热题,指针
From: https://blog.csdn.net/Young_4/article/details/145076785

相关文章

  • 代码随想录算法训练营第4天 | 24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面
    一、刷题部分1.124.两两交换链表中的节点原文链接:代码随想录题目链接:24.两两交换链表中的节点-力扣(LeetCode)1.1.1题目描述给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。示例1:输......
  • 【Leetcode 热题 100】739. 每日温度
    问题背景给定一个整数数组tempera......
  • 3.1.链表
    链表链表是一种常见的基础数据结构,它由一系列节点组成,这些节点不必在内存中相连,而是通过指针相互连接,形成一个链式结构。以下是链表的详细定义:节点结构:链表中的每个节点至少包含两个部分,即数据域和指针域。数据域:用于存储节点的数据,可以是各种数据类型,例如整数、字符、字......
  • 梦开始的地方:力扣热题100哈希表
    文章目录前言一、哈希表是什么二、力扣解题常见的三种哈希结构(java版本)1.数组2.set(集合)3.map(映射)总结前言在刷力扣100题的征程中,我从哈希相关题目入手,一路探索,收获颇丰。如今,想将自己在这一过程中的思路与感悟进行一番总结,既为记录成长,也希望能给同样在算法之路上......
  • List详解 - 双向链表的操作
    在C++中,std::list是标准模板库(STL)中的一个容器,它实现了双向链表的数据结构。与数组或向量(std::vector)不同,std::list允许在常数时间内进行插入和删除操作,尤其是在链表的任意位置。本文将详细介绍std::list的基本操作,并通过示例代码帮助读者理解其使用方法。1. std::list 的基......
  • LeetCode:141.环形链表
    //双指针快+1=慢trueclassListNode{constructor(val,next){this.val=(val===undefined?0:val)this.next=(next===undefined?null:next)}}varhasCycle=function(head){letfast=headletslow=headwhile(......
  • LeetCode:83.删除排序链表中的重复元素
    LeetCode:83.删除排序链表中的重复元素classListNode{constructor(val,next){this.val=(val===undefined?0:val)this.next=(next===undefined?null:next)}}vardeleteDuplicates=function(head){letp=head//head......
  • 力扣21、合并两个有序链表
    目录1、题目2、思路3、代码若有错误,欢迎指正! 1、题目将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例......
  • 数据结构——单链表(C语言版:超详细)
    目录一、引言1.数据结构的重要性2.单链表在其中的地位二、什么是单链表1.单链表的定义2.基本概念解释三、单链表的结构特点1.与数组对比的优势2.存在的劣势四、单链表的基本操作1.节点的创建2.动态申请一个节点3.插入节点3.1尾插3.2头插3.3在pos之前插入3.4在......
  • 代码随想论算法训练营第3天 | 链表理论基础,203.移除链表元素,707.设计链表,206.反转链表
    一、刷题部分1.1链表理论基础原文链接:代码随想录题目链接:......