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

剑指offer20_链表中环的入口节点

链表中环的入口节点


给定一个链表,若其中包含环,则输出环的入口节点。

若其中不包含环,则输出null

数据范围

节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]

节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]

样例

QQ截图20181202023846.png

给定如上所示的链表:
[1, 2, 3, 4, 5, 6]
2
注意,这里的2表示编号是2的节点,节点编号从0开始。所以编号是2的节点就是val等于3的节点。则输出环的入口节点3.

题解

使用双指针技巧检测链表中是否存在环,并确定环的入口节点。

O(n)线性时间复杂度,每个节点最多被访问两次。

阶段一:检测环是否存在

  1. 初始化两个指针:
    • first(慢指针):每次前进1步
    • second(快指针):每次前进2步
  2. 同时从链表头节点开始移动:
    • second遇到nullptr链表无环
    • firstsecond相遇 → 链表有环

阶段二:定位环入口

  1. first移回链表头部
  2. second保持在相遇点不动
  3. 两指针改为每次各前进1步
  4. 当两指针再次相遇时 → 相遇点即为环的入口

数学原理

设:

  • 链表头到环入口距离:a
  • 环入口到首次相遇点距离:b
  • 首次相遇点到环入口距离:c

则有:

  1. 首次相遇时:
    • first移动距离:a + b
    • second移动距离:a + b + k*(b + c) (k为绕环圈数)
  2. 由速度关系(2倍速):2(a + b) = a + b + k(b + c)=> a = (k-1)(b + c) + c
头节点
环入口
C
D
首次相遇点
F

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *entryNodeOfLoop(ListNode *head) {if(!head || !head->next) return nullptr;auto first = head, second = head;while(first && second){first = first->next;second = second->next;if(second) second = second->next;else return nullptr;if(first == second){first = head;while(first != second){first = first->next;second = second->next;}return first;}}return nullptr;}
};

示例1:有环链表

1234↑     ↓65
  1. 阶段一:
    • slow: 1→2→3→4→5→6
    • fast: 1→3→5→2→4→6
    • 在节点6相遇
  2. 阶段二:
    • slow重置到1,fast保持在6
    • slow:1→2
    • fast:6→2
    • 在节点2相遇 → 环入口是2

示例2:无环链表

1234 → nullptr

阶段二:

  • slow重置到1,fast保持在6
  • slow:1→2
  • fast:6→2
  • 在节点2相遇 → 环入口是2

示例2:无环链表

1234 → nullptr
  • fast指针会先到达nullptr → 无环
http://www.xdnf.cn/news/13096.html

相关文章:

  • 408第一季 - 数据结构 - 折半查找与二叉排序树
  • Java面向对象思想以及原理以及内存图解
  • 【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
  • while/do while/for循环几个小细节
  • Android Native 之 lmkd进程和kernel kswapd的关联
  • 树突状细胞与肿瘤
  • 在Mathematica环境中做数值实验来观察逻辑映射的复杂度
  • SPI Flash开发全解(基于GD25Qxx)
  • 选取货物 - 题解(0-1背包问题)
  • Ⅳ.计算机二级选择题(函数)
  • IP选择注意事项
  • #Vue3篇:透传 Attributes---$attrs插槽propemit
  • Java并发编程实战 Day 15:并发编程调试与问题排查
  • 力扣-20.有效的括号
  • 多进程通信之共享内存
  • 0,freeRTOS基础知识
  • SpringBoot API接口签名(防篡改)
  • win11 找不到 GPEDIT.MSC Win11找不到gpedit.msc怎么办?Win11提示缺少gpedit.msc文件怎么办???
  • PyCharm 和 Anaconda 搭建Python环境【图文教程】
  • 32位寻址与64位寻址
  • 轻量级屏蔽文件管理方案
  • Ascend NPU上适配Step1X-Edit模型
  • 线程池与并发工具:让并发编程更简单、高效!
  • CodeRider 2.0 体验手记:当 AI 编程照进现实,颠覆想象的开发之旅
  • 【51单片机】4. 模块化编程与LCD1602Debug
  • 中国大学本科专业采用‌学科门类—专业类—具体专业‌三级体系
  • 【DAY44】预训练模型
  • sql语句执行流程
  • 指令管理—弹幕/礼物/快捷键—抖音直播伴侣—使用教程
  • omi开源程序是AI 可穿戴设备的源码。戴上它,说话,转录,自动完成