LeetCode第287题 寻找重复数(快指针比慢指针可能不止多走一圈)(Java)

题目出处

这一题的标准解法是用快慢指针,没错,就是快慢指针。在这里记录一下我的解题历程。

一开始我和评论区的快指针比慢指针只多走一圈的想法一致,但是没有证明,所以我打算先以这个命题为基础,看看题目能不能解出来。

根据题目条件,可以归为链表问题,即数组中的每一个数存储的都是下一个数的索引,由于有重复元素,加上题目所给的数组中元素的取值,所以构成的链表最终一定会在某处结成一个环,这就导致快指针一定是可以追到慢指针的。然而难点在于如何找到环的入口位置,也即重复元素。这个问题可以用画图来解释:

在这里插入图片描述
所以,当快指针追上慢指针时,要将快指针清零,然后快慢指针相等时,即它们同时到达了入口,取出该值即重复数。

代码如下:

public int findDuplicate(int[] nums) {
        int slow = 0;
        for (int fast = 0; slow != fast || fast == 0; ) {
            slow = nums[slow];
            fast = nums[nums[fast]];
            // System.out.println("slow: " + slow + "  fast: " + fast);
        }
        // System.out.println(slow);
        // System.out.println("----------");
        for (int i = 0; slow != i; i = nums[i]) {
            // System.out.println("slow: " + slow + "  fast: " + i);
            slow = nums[slow];
        }
        // System.out.println("slow: " + slow + "  fast: " + slow);

        return slow;
    }

然而,上面的结论是基于快指针只比慢指针多走一圈得出的,其实,快指针是可能比慢指针多走不止一圈的。比如,这个用例:[1, 2, 3, 4, 5, 6, 7, 10, 9, 10, 8],这个用例是快指针比慢指针多逗乐两圈,同样地,我们可以模仿上面列出式子:

在这里插入图片描述
其实,最后找入口的时候,相当于快指针多饶了两圈,最后结果并没有改变。

优化后的代码,如下:

public int findDuplicatePro(int[] nums) {
        int slow = 0;
        int fast = 0;
        while (true) {
            slow = nums[slow];
            fast = nums[nums[fast]];

            if (slow == fast) {
                fast = 0;
                while (slow != fast) {
                    slow = nums[slow];
                    fast = nums[fast];
                }
                return slow;
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值