leetcode 287.Find the Duplicate Number(找重复数字)

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Example 1:

Input: [1,3,4,2,2]
Output: 2
Example 2:

Input: [3,1,3,4,2]
Output: 3
Note:

You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.

给出一个包含n+1个整数的数组,包含1~n(包含n),找出重复的数字

附加条件:
不能修改数组,也就是不能用排序
只能用O(1) 的额外空间,也就是不能用hashset之类的保存数字
runtime小于O(n2),也就是不能用brute force搜索

思路
本质上是链表中存在环,找环入口的问题。

为什么是链表的环?且把数组中每个数字看作数组下标(因为本来应该是1~n的下标,对应1~n的数字)来看。
以前在链表中走一步是把指针右移,即指针++,
这里的走一步是找到nums中对应下标的数字,即nums[pointer],走两步就是nums[nums[pointer]]。

可以看example1: [1,3,4,2,2]
从下标0开始,nums[0] = 1, 然后nums[1] = 3, nums[3] = 2, nums[2] = 4, nums[4] = 2,
看到这里出现了环,nums[3] == nums[4]。

找到环的入口在142. 链表环中见过,
用快慢指针,快指针每次走两步,慢指针每次走一步,它们相遇就是存在环。
然后慢指针回到起点,快慢指针每次都走一步,它们相遇的地方即是环的入口,也就是重复的元素。

    public int findDuplicate(int[] nums) {
        int n = nums.length;
        int slow = 0;
        int fast = 0;
        
        while(true) {
            slow = nums[slow];
            fast = nums[nums[fast]];
            if(slow == fast) break;
        }
        
        slow = 0;
        
        while(true) {
            slow = nums[slow];
            fast = nums[fast];
            if(slow == fast) break;
        }
        return slow;
    }

参考 Floyd算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝羽飞鸟

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

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

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

打赏作者

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

抵扣说明:

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

余额充值