LeetCode 287. Find the Duplicate Number

来源:互联网 发布:关于域名说法正确的是 编辑:程序博客网 时间:2024/05/17 08:01

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.

Note:

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


题目大意:

题目中给定一个长度为n+1的数组nums,并且这个数组中的元素取值范围是[1,n],但是其中存在重复的元素,重复的元素只有一种。


根据题目的要求用一般的方法肯定是不行的,在这里就不再赘述了。直接给出正确的做法和思路:

先试想一下没有重复元素的情况,有n+1个数字,数组元素为{1,2,3,4...n+1},我们假设每一个数为一个指针,指向数组下标为该数的元素。那么n+1有没有可以指向的元素,因为数组下标最大为n(从0开始)。


现在给定数组长度是n+1,元素的取值范围是[1,n],有两个数字是相同的,也就是说这两个数字指向的下一个数字是相同的,也就是说这个链表中是有环的。如图所示。

很明显,画三角的那个地方的元素就是重复元素,因为有两处的元素都指向它。现在我们要做的就是求出这个环的起点的元素。

如果两个人从操场起点同时出现,A的速度为1,B的速度为2,那么当B跑了一圈回到起点的时候,A跑了一半;当B跑完第二圈回到起点时,A刚好跑完第一圈回到起点。A和B相遇。


如果在如上图所示的起点,A和B同时出发,当B从起点跑到三角处的时候,A到大的位置是从起点到三角处的中间位置,很明显当B从三角处再次到达三角处的时候,A一定还没有到达三角处,因此A和B会在三角处之间相遇。这里假设途中的点为相遇处,a,b,c为三段线的距离。


当A和B相遇的时候,B速度是2,走的距离是a+b+c+b ;A的速度是1,走的距离是a+b。

因为时间是相同的 于是我们得到等式 (a+c+b+b)/2 = (a+b)/1得到 a=c。

既然a=c也就是说当A和B相遇以后,C以相同的速度从起点出发,B和C相遇的地方就是相同元素。


下面给出一个例子方便大家理解。

数组nums={2,5,9,6,9,3,8,9,7,1}




题目代码:

class Solution {public:    int findDuplicate(vector<int>& nums) {        int f = nums[nums[0]];        int s = nums[0];        while(s != f){            f = nums[nums[f]];            s = nums[s];        }        f = 0;        while(s != f){            s = nums[s];            f = nums[f];        }        return s;    }};


原创粉丝点击