双指针巧解链表有环问题

这篇具有很好参考价值的文章主要介绍了双指针巧解链表有环问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

链表有环问题可以使用双指针技巧轻松解决。

  • 判断链表是否有环问题,可以通过设置快慢指针同向遍历链表,若相遇则有环。

  • 找环入口问题,也可以通过设置快慢指针同向遍历链表,寻找相遇点。不同的是,当两指针相遇后,快指针回到链表头节点,慢指针留在相遇节点,两者同速遍历,二次相遇点一定是环入口

下面两道题精选于牛客网面试必刷TOP101,相信我,十分简单,非常容易理解!

欢迎来到我的博客 柿子先生的半亩良田,查看更多优质内容。


BM6 判断链表中是否有环

描述

判断给定的链表中是否有环。如果有环则返回 true,否则返回 false。

思路

双指针

线性与环形链表特点:
  • 线性链表末尾一定有 null。

  • 环形链表的环一定在末尾,末尾没有 null 了。

线性与环形链表结束条件:
  • 线性链表的结束条件就是遍历到 null。

  • **环形链表会不断循环,需要借助双指针才能结束。**同向访问的双指针,因为速度不同,只要有环,二者一定能相遇。

F1:双指针
步骤
  1. 设置快慢两指针,初始都指向链表头;
  2. 遍历链表,快指针每次走两步,慢指针每次走一步;
  3. 如果快指针到了链表末尾,说明没有环,因为它每次走两步,所以要验证连续两步是否为 null;
  4. 如果链表有环,那快慢双指针会在环内循环,因为快指针每次走两步,因此快指针会在环内追到慢指针,二者相遇就代表有环。

双指针巧解链表有环问题

代码
public boolean hasCycle(ListNode head) {
    // 先判断链表为空的情况
    if (head == null)
        return false;
    // 1. 设置快慢两指针,初始都指向链表头
    ListNode fast = head;
    ListNode slow = head;
    // 2. 遍历链表
    // 3. 如果没环,fast 会先到链表尾
    while (fast != null && fast.next != null) {
        // 快指针移动两步
        fast = fast.next.next;
        // 慢指针移动一步
        slow = slow.next;
        // 相遇则有环
        if (fast == slow)
            return true;
    }
    // 到末尾,则没有环
    return false;
}
时间复杂度

O ( M ) O(M) O(M)

最坏情况下遍历链表 n 个节点。

空间复杂度

O ( 1 ) O(1) O(1)

仅使用了两个指针,没有额外辅助空间。


BM7 链表中环的入口点

描述

给一个长度为 n 链表,若其中包含环,请找出该链表的环的入口结点,否则,返回 null。

分解任务
  1. 判断链表是否有环;
  2. 在有环的链表中找到环的入口。
思路

双指针

如何找到环的入口

一个有环链表。

假设快指针在环中走了 n n n 圈,慢指针走了 m m m 圈,两者相遇。

链表头节点到环入口点距离为 x x x,环入口到相遇点距离为 y y y,相遇点到环入口点距离为 z z z

快指针一共走了 x + n ( y + z ) + y x + n(y + z) + y x+n(y+z)+y 步,慢指针一共走了 x + m ( y + z ) + y x + m(y + z) + y x+m(y+z)+y 步。

快指针走的步数是慢指针的两倍,则
x + n ( y + z ) + y = 2 ( x + m ( y + z ) + y ) x + n(y + z) + y = 2(x + m(y + z) + y) x+n(y+z)+y=2(x+m(y+z)+y)
进一步推导,
x + y = ( n − 2 m ) ( y + z ) x+y=(n-2m)(y+z) x+y=(n2m)(y+z)
因为环的大小是 y + z y+z y+z,说明从链表头经过环入口到达相遇地方经过的距离等于整数倍环的大小。那么,我们从头开始遍历到相遇位置,和从相遇位置开始在环中遍历,会使用相同的步数,而双方最后都会经过入口到相遇位置这 y y y 个节点,说明这 y y y 个节点它们就是重叠遍历的,那它们从入口位置就相遇了,这样就找到了入口节点。

F1:双指针
步骤
  1. 使用 BM6 方法判断链表是否有环,并找到相遇节点。
  2. 慢指针继续在相遇节点,快指针回到链表头,两个指针同步逐个元素开始遍历链表。
  3. 两者再次相遇的地方就是环的入口。

双指针巧解链表有环问题

代码
// 寻找链表中环的入口节点
public ListNode entryNodeOfLoop(ListNode pHead) {
    ListNode slow = hasCycle(pHead);
    // 没有环
    if (slow == null)
        return null;
    // 有环
    // 快指针回到表头
    ListNode fast = pHead;
    // 再次相遇即是环入口
    while (fast != slow) {
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

// 判断有没有环
public ListNode hasCycle(ListNode head) {
    // 先判断链表为空的情况
    if (head == null)
        return null;
    // 快慢双指针
    ListNode fast = head;
    ListNode slow = head;
    // 如果没环,快指针会先到链表尾
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
        // 相遇则有环,返回相遇的节点
        if (slow == fast) {
            return slow;
        }
    }
    // 到末尾说明没有换,返回 null
    return null;
}
时间复杂度

O ( n ) O(n) O(n)

最坏情况下遍历链表两次

空间复杂度

O ( 1 ) O(1) O(1)

使用了常数个指针,没有额外辅助空间文章来源地址https://www.toymoban.com/news/detail-408301.html

到了这里,关于双指针巧解链表有环问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 哪些方法可以判断出一个有向图是否有环

    使用 深度优先遍历 ,若从有向图上的某个顶点u出发,在 DFS(u)结束之前出现一条从顶点v到u的边,由于v在生成树上是u的子孙,则图中必定存在包含u和v的环,因此深度优先遍历可以检测一个有向图是否有环。 拓扑排序 时,当某顶点不为任何边的头时才能加入序列,存在环时环中的

    2024年02月12日
    浏览(35)
  • 华为OD 面试手撕代码真题【判断链表是否有环】

    判断链表是否有环         面试官口述题目,要求实现函数,输入是一个头节点,输出是一个bool值。         相当经典的题目了,感觉面试官要是出这个题,应该是觉的你还不错,出个简单的做出来就完事儿了。剑指offer或者leetcode上的老题了,但是手撕代码经典的问题还是

    2024年02月10日
    浏览(38)
  • C/C++ BM6判断链表中是否有环

    做了一堆单链表单指针的题目,这次是个双指针题,这里双指针的作用非常明显。 判断给定的链表中是否有环。如果有环则返回true,否则返回false。 数据范围:链表长度 0≤n≤10000,链表中任意节点的值满足 ∣val∣=100000 要求:空间复杂度 O(1),时间复杂度 O(n) 输入分为两部

    2024年01月19日
    浏览(31)
  • 【JavaSE专栏49】Java集合类LinkedList解析,链表和顺序表有什么不同?

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了 Java 中集合类 LinkedList 的语法、使用说明和应用场景,并给出了样例代码

    2024年02月16日
    浏览(31)
  • 为什么深度优先搜索可以判定简单图中是否有环,而宽度优先搜索不行?

    1,首先可以肯定的是,对于无向图而言,宽搜和深搜都能判断是否有环。 简要说明一下,假如一个无向图有环,那么在宽搜的过程中,能搜到已经访问过的结点。如果一个无向图没有环(参考无向树),那么它的宽度优先搜索过程中,是不会访问到已访问过的结点的。 对于

    2024年02月14日
    浏览(44)
  • leetcode 141.环形链表 I - 142.环形链表 II 代码及指针相遇证明问题

    给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 如果链表中存在环 ,则返回 true 。 否则,返回 false 。 思路: 快慢指针问题 。我们可以声明一个 fast 指针(一次走两步),声明一个 slow

    2024年02月12日
    浏览(53)
  • 算法通关村第一关——链表经典问题之双指针笔记

    基本结构 1.寻找中间结点 2.寻找倒数第k个元素 3.旋转链表

    2024年02月14日
    浏览(34)
  • 算法通关村第一关——链表经典问题之双指针专题笔记

    我一直觉得双指针是一个非常好用的方法,在链表中可以使用,在数组中依然可以,很灵活。 1. 寻找中间结点         用两个指针 slow 与 fast 一起遍历链表。slow 一次走一步, fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。 2. 寻找倒数第K个元素 在这

    2024年02月15日
    浏览(29)
  • LeetCode算法小抄 -- 链表(快慢指针、双指针、回文链表)

    ⚠申明: 未经许可,禁止以任何形式转载,若要引用,请标注链接地址。 全文共计10077字,阅读大概需要10分钟 🌈更多学习内容, 欢迎👏关注👀文末我的个人微信公众号:不懂开发的程序猿 个人网站:https://jerry-jy.co/ Collection 子接口之 Queue (LeetCode上经常用,手撕算法题!

    2023年04月08日
    浏览(27)
  • 【链表OJ 11】复制带随机指针的链表

    前言:  💥🎈个人主页:​​​​​​Dream_Chaser~ 🎈💥 ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 leetcode138. 复制带随机指针的链表 1. 问题描述 2.代码思路: 2.1拷贝节点插入到原节点的后面 2.2控制拷贝节点的random     2.3拷贝节点解下来尾插组成拷

    2024年02月09日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包