<leetcode> 287. Find the Duplicate Number 数组中的重复数

Note:和《剑指offer》面试题3:数组中的重复数字 类似

解法一:映射找环法O(n)

我当时想到的解法,要么时间复杂度不合要求,要么空间复杂度不合要求,看了这道题的discussion区,结合两个回答,总算是明白了这道题该怎么解比较简单。
两个回答的链接:
- Java O(n) time and O(1) space solution. Similar to find loop in linkedlist.
- My easy understood solution with O(n) time and O(1) space without modifying the array. With clear explanation.


题目: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.

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.

代码如下:

public int findDuplicate(int[] nums) {
        if (nums.length > 1){
            int slow = nums[0];
            int fast = nums[nums[0]];
            //以下为求两个指针第一次相遇的点
            while (slow != fast){
                slow = nums[slow];
                fast = nums[nums[fast]];
            }

            fast = 0;
            //以下求重复元素的节点,即重复元素的入口节点
            while (fast != slow){
                fast = nums[fast];
                slow = nums[slow];
            }
            return slow;
        }
        return -1;
    }

思路
例如下面这个数组:

index: 0 1 2 3 4 5
value: 1 2 3 2 1 4

因为数组值的特殊性,所以配合其索引index,可以形成index的图,又因为有重复的数字存在,所以图的某个部分会形成一个circle,circle的入口为重复的那个数。

该数组索引形成的图为:
index形成的图
第一部分,如果安排一个slow的index(每次一步)和fast的index(每次两步),它们走着最终会在circle中一直循环出不去,但迟早会相遇。类似数学题中的,甲乙以不同速度同向出发,最终快的会赶上慢的。然而,相遇停下的地方不一定是circle入口。
第二部分,一个index从0出发,一个从停下的位置出发,步长都为1。假设circle之前的直线长度为m(不包括circle入口),circle长度为n,相遇点在circle的第k处(circle入口为第1处),则fast走过的路程为m + i*n + k,slow走过的路程为m+j*n+k,二者所花时间相等,速度已知。可得,等式(m + i*n + k)/2 = m+j*n+k ==> m = (i-2j)*n - k;(i-2j)不为0,令s = i - 2j,s为正整数,则m = sn - k , m = (s-1)n + (n - k)。slow正在k点,这个特殊关系使得如果将fast放回0点,当fast到达circle的入口时走了m步,而slow走了(n - k)又绕了(s-1)n圈回到了circle的入口处,它们的相遇点正好是入口。

解法二:二分法O(n*lgn)

利用鸽巢原理的二分解法
上面这个链接解释的很清楚了,一看就懂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值