zoukankan      html  css  js  c++  java
  • LeetCode 287. Find the Duplicate Number

    Find the Duplicate Number | LeetCode OJ
    https://leetcode.com/problems/find-the-duplicate-number/

    这个题目属于编码比较简单但解法分析过程比较复杂。

    首先,把1~n放入0~n个元素,必定有两个或以上元素重复。数字里没有0,所以从下标0出发不会再回到最初的元素0。

    假设当前的下标为x,下一步的下标为f(x),若f(x) = A[x], 也即每次跳到一个元素,则下一步移动到当前元素值对应的元素下标。我们来证明这样的移动存在环:

    假设重复的元素值为x.

    假设x存在于A[1..n]中,A[i] 和A[j]的值为x。除去i,j,A[1..n]还剩下n-2个元素,若A[x]值为i,j,x之一,显然这是一个环。假设A[x]的值为k,k!=x && k!=i && k!=j,则剩下n-3个元素。因为重复的元素只有x,所以剩下的元素值不能为k,这样我们只有n-4个不重复的值可用,如果要填入n-3个元素,或者这n-4个元素有重复,这和假设矛盾,或者只能填入i,j,x之一。这样就形成了一个环。

    A[0]=x的情况证明也类似。

    既然证明了这种遍历方式存在环,我们就可以套用 Linked List Cycle II 的思路来找到环的起点。此处不赘述。

    详细分析可以参考这篇:http://keithschwarz.com/interesting/code/?dir=find-duplicate

     代码如下:

    class Solution {
    public:
        int findDuplicate(vector<int>& nums) {
            if(nums.size() <= 1){
                return -1;
            }
            
            int fast = 0, slow = 0;
            do{
                fast = nums[nums[fast]];
                slow = nums[slow];
            }while(fast != slow);
            
            fast = 0;
            while(fast != slow){
                fast = nums[fast];
                slow = nums[slow];            
            }
            
            return slow;
        }
    };

     

  • 相关阅读:
    590. N 叉树的后序遍历
    CF605E
    网络流水题题单
    wqs二分的边界
    luoguP6326 Shopping
    【THUWC2020】工资分配
    CF1336简要题解
    「PKUWC2020」最小割
    洛谷P4895 独钓寒江雪
    省选联考2020简要题解
  • 原文地址:https://www.cnblogs.com/k330/p/5496526.html
Copyright © 2011-2022 走看看