leetcode 142. 环形链表 II(双指针)【Floyd判圈法】

题意

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
在这里插入图片描述

解题思路

① 设双指针 f a s t fast fast s l o w slow slow ,其中 f a s t fast fast 每次前进2步、 s l o w slow slow每次前进1步。如果 f a s t fast fast 最终为NULL,那么该链表无环;反之, f a s t fast fast s l o w slow slow必会在某一点相遇。
② 设 f a s t fast fast s l o w slow slow相遇的点为 P P P,那么 s l o w slow slow P P P点开始, f a s t fast fast从起始点,两个指针同时每次都前进一步,那两者最终相遇的地方即链表入环的第一个节点。

代码

/**
 * 给定一个链表,如果有环路,找出环路的开始点。
 *
 * @author ZhangLingRan
 */

class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
        next = null;
    }
}

/**
 * @author ZhangLingRan
 */
public class Solution{

    public ListNode detectCycle(ListNode head) {

        ListNode fast = head, slow = head;
        
        do {
	        // 如果fast走到头,说明没环,那么返回NULL
	        if (fast == null || fast.next == null) {
	            return null;
	        }
            fast = fast.next.next;
            slow = slow.next;
        } while (fast != slow);

        //如果有环,那么找到第一次相遇的交点,slow从交点往后走、fast从head往后走,直到相遇即为交点
        slow = head;
        while (fast != slow) {
            fast = fast.next;
            slow = slow.next;
        }

        return slow;
    }
}

方法的数学证明

在这里插入图片描述
假设这是一个带有环的链表;其中 O Q OQ OQ的长度为 L 1 L1 L1,环的长度为 L 2 L2 L2;两个指针在 P P P点相遇,那么当指针 s l o w slow slow走到了 P P P点,其走过的路程为 ∣ O P ∣ = L 1 + ∣ Q P ∣ |OP| = L1+|QP| OP=L1+QP,那么 f a s t fast fast指针走过的路程为 2 ∣ O P ∣ = L 1 + k L 2 + ∣ Q P ∣ 2|OP| = L1+kL2+|QP| 2OP=L1+kL2+QP
由此可知:
2 ∣ O P ∣ = L 1 + k L 2 + ∣ Q P ∣ = 2 ( L 1 + ∣ Q P ∣ ) 2|OP| = L1+kL2+|QP| = 2(L1+|QP|) 2OP=L1+kL2+QP=2(L1+QP)
化简得
k L 2 = ∣ Q P ∣ + L 1 kL2 = |QP| + L1 kL2=QP+L1

L 1 = ∣ O Q ∣ = k L 2 − ∣ Q P ∣ = ( k − 1 ) L 2 + L 2 − ∣ Q P ∣ = ( k − 1 ) L 2 + ∣ P Q ∣ L1 = |OQ| = kL2 - |QP| = (k-1)L2 + L2 - |QP| = (k-1)L2 + |PQ| L1=OQ=kL2QP=(k1)L2+L2QP=(k1)L2+PQ
其中 ∣ Q P ∣ |QP| QP表示从 Q Q Q点到 P P P点走过的路程, ∣ P Q ∣ |PQ| PQ表示从 P P P点到 Q Q Q的走过的路程。
L 1 = ∣ P Q ∣ + ( k − 1 ) L 2 L1 = |PQ| + (k-1)L2 L1=PQ+(k1)L2 可知,当慢指针从 O O O点走到了入环点 Q Q Q点的时候,快指针将会绕环(k-1)圈之后,与慢指针同时到达Q点。

Floyd判圈法的变形题目

leetcode 287. 寻找重复数

题目解决方案分析:

根据题目要求,需要在包含 n + 1 个整数的数组 nums 中(其数字都在 1 到 n 之间(包括 1 和 n)),找到存在的一个重复的整数。

由题意可以知道,数组中元素的值不会超过n,那么可以根据元素来构建一个链表,即nums[0]的下一个节点为 nums[nums[0]];

由于数组存在重复元素(假设为 nums[i] 和 nums[j]),因此,在构建的这个链表中,必然有nums[i]的下一个节点为 nums[nums[i]],且nums[j]的下一个元素是nums[nums[j]]=nums[nums[i]];

因此,如果两个元素,fast和slow,使得nums[fast] = nums[slow],则fast与slow即是相同的两个元素;

如数组 [1,3,4,2,2]

那么其构成的链表结构为:
在这里插入图片描述
如上,最终的结果即为2;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhang L.R.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值