判断链表是否有环&找入环点@Leetcode —— 带环链表问题

简介: 判断链表是否有环&找入环点

1. 判断链表是否有环

1.1 题目

题目链接:链表带环问题
在这里插入图片描述

1.2 思路及题解

这道题要说思路很简单,还是应用了“快慢指针”的思想。
【结论】快指针fast一次走两步,慢指针slow一次走一步。若带环fast会在环内追上slow如果无环,永远不可能再相遇,且·fast会先为空。

这样我们可以很轻易的写出代码。这只是最基本的追及问题,同时也严谨的疑惑着,为什么快指针一次走两步慢指针一次走一步可以?快指针一次走3、4、n步行吗?这道题目重点在于如何推导出上述结论。

bool hasCycle(struct ListNode *head) {
    struct ListNode * slow = head;
    struct ListNode * fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
            return true;
    }
    return false;
}
 

1.3 证明

:black_heart: 1. 为什么slowfast一定会在环中相遇?会不会错过,永远遇不上?
slowfast,一定是fast先进环,此时slow走了进环前距离的一半。
随着slow进环,fast已经在环内走了一段(走了多少跟环的大小有关)。设slow进环时,fastslow距离是$N$,则slowfast每追一次,差距缩小一步,判断一下是否相遇,距离变化$N-1,N-2,N-3 ,....2,1,0$。一定会到0,则一定能相遇。
在这里插入图片描述

:black_heart: 2. 为什么slow走一步,fast走两步?能不能fast走3/4/5/n步?
结论:fast走$n(n>2)$步,不一定能遇上

(1)fast一次走三步
在这里插入图片描述
(2)fast一次走4步
在这里插入图片描述

fast走$N$步,$N$再变大,以此类推,都是不行的。

2. 找入环点

2.1 题目

题目链接:找到环的入口点
在这里插入图片描述

2.2 思路及证明

slow走一步,fast走两步,一定会相遇,如何求环的入口点呢?
【结论】一个指针从相遇点开始走,另一个指针从链表头开始走,它们会在环的入口点相遇。
【证明】追上的过程中
慢指针走的距离:$L+x$ (慢指针不可能超过一圈,$N<C$)
快指针走过的距离:$L+n*c+x$
快指针走过的路程是慢指针的2倍:$2(L+x) = L+n*c+x$
在这里插入图片描述
在这里插入图片描述

2.3 题解

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    struct ListNode* meetnode = NULL;
    //1.找到他们相遇的点
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(fast == slow)
        {
            //相遇
            meetnode = fast;
            //寻找入环点--公式证明
            while(head != meetnode)
            {
                head = head->next;
                meetnode = meetnode->next;
            }
            return meetnode;
        }
    }
    return NULL;
}

持续更新中@边通书

相关文章
|
1月前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
28 0
|
1月前
|
Python
【Leetcode刷题Python】25.K 个一组翻转链表
解决LeetCode "K 个一组翻转链表" 问题的三种方法:使用栈、尾插法和虚拟节点顺序法,并提供了每种方法的Python实现代码。
26 0
|
1月前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
1月前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
1月前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
1月前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
1月前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
21 3
【Leetcode刷题Python】114. 二叉树展开为链表
|
23天前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。
|
1月前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
1月前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表