287. 寻找重复数

 

 

 

 1 使用数组中的值作为索引下标进行遍历,遍历的结果肯定是一个环(有一个重复元素)
 2 检测重复元素问题转换成检测环的入口
 3 为了找到环的入口,可以进行如下步骤:
 4 
 5 设置两个快慢指针, fast每次走两步,slow每次走一步,最终走了slow走了n步与fast相遇,fast走了2*n,fast可能比slow多饶了环的i圈,得到环的周长为n/i
 6 slow指针继续走, 且另设第三个指针每次走一步,两个指针必定在入口处相遇
 7 假设环的入口和起点的距离时m
 8 当第三个指针走了m步到环的入口时
 9 slow刚好走了n + m步,换句话说时饶了环i圈(环的周长为n/i)加m步(起点到入口的距离)
10 得到相遇的是环的入口,入口元素即为重复元素
11 
12 class Solution 
13 {
14 public:
15     int findDuplicate(vector<int>& nums) 
16     {
17         int fast = 0,slow = 0;
18         while(true)
19         {
20             fast = nums[nums[fast]];
21             slow = nums[slow];
22             if(fast == slow) break;
23         }
24         fast = 0;
25         while(true)
26         {
27             fast = nums[fast];
28             slow = nums[slow];
29             if(fast == slow) break;
30         }
31         return slow;
32     }
33 };

 

//[1,3,4,2,2]

//n个抽屉放入n+1个数,肯定有一个数重合
//[1,2,3,4]   [l,mid] = [1,2]的数有三个 > mid-l+1,更新r = mid

class Solution 
{
public:
    int findDuplicate(vector<int>& nums) 
    {
        int n = nums.size() - 1;
        int l = 1,r = n;
        while(l < r)
        {
            int mid = l + r >> 1;

            int cnt = 0;
            for(auto x : nums)//找到[l,mid]中的个数
            {
                if(x >= l && x <= mid) cnt++;
            }

            if(cnt > mid - l + 1) r = mid;
            else l = mid + 1;
        }
        return r;
    }
};

 

posted @ 2020-03-21 17:05  Jinxiaobo0509  阅读(138)  评论(0)    收藏  举报