Leetcode ☞ 287. Find the Duplicate Number ☆

287. Find the Duplicate Number

My Submissions
Question
Total Accepted: 20936  Total Submissions: 55237  Difficulty: Hard

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.














我的AC【弄个新数组,排序后比较相邻两值(错错错=。=  因为还是相当于modify the array了。我就说嘛,hard难度的题不可能这样就搞定..)】:

<span style="font-size:14px;">int comp(const int *a, const int *b){
    if (*a >= *b) return 1;
    else return -1;
}

int findDuplicate(int* nums, int numsSize) {
    int* c = nums;
    qsort(c, numsSize, sizeof(int), comp);
    for(int i = 0; i < numsSize ; i++){
        if (c[i] == c[i + 1])
            return c[i];
    }
}</span>

此题真正的两种做法:1.二分查找  2.快慢指针

1.二分查找 binary search

思路:

设 low为左值, high为右值, mid 为两者的中间值。这里的 low, high, mid 均是指元素的值,不是指下标,之所以可以这么做,是因为题目的条件“ n+1 长的数组里面只有 1...n 的数值”。

1>.将数组扫一遍,得到大于等于 low 且 小于等于 mid 的元素个数,即为 count。

2>.当 count 大于 本应该有的个数,,说明重复值在[low,mid]之间,缩小范围。

3>.当 count 小于等于 本应该有的个数,说明重复值在 [mid, high] 之间,缩小范围。

4>.重复前面步骤,直到找到重复值。

int findDuplicate(int* nums, int numsSize) {
    int low = 1, high = numsSize - 1, mid;
    
    while (low <= high) {
        mid = low + (high - low) / 2;
        int count = 0;
        
        for (int i = 0; i < numsSize; i++) {
            if (nums[i] <= mid)
                count++;
        }
        
        if (count <= mid)
            low = mid + 1;
        else
            high = mid - 1;
/*
        if(count > mid)
            high = mid;
        else
            low = mid + 1; 
*/
    }
    
    return low;
}


2.快慢指针 two pointer

思路:因为有数字可能出现多次,会有 i != j, nums[i] == nums[j]。

This algorithm also called Floyd's cycele detection algorithm。

<span style="font-size:14px;">int findDuplicate(int* nums, int numsSize) {</span>
<span style="font-size:14px;">    int slow = 0;
    int fast = 0;
    int finder = 0;

    while (1)
    {
        slow = nums[slow];
        fast = nums[nums[fast]];

        if (slow == fast)
            break;
    }
    while (1)
    {
        slow = nums[slow];
        finder = nums[finder];
        if (slow == finder)
            return slow;
    }
    
}
/*
最后一段while也可写成:
        fast = 0;  
        while(1)  
        {  
            slow=nums[slow];  
            fast=nums[fast];  
            if(slow==fast)return slow;  
        }</span>
*/


此题的快慢指针+详细解释

https://leetcode.com/discuss/61514/understood-solution-space-without-modifying-explanation

https://leetcode.com/discuss/61086/java-time-and-space-solution-similar-find-loop-in-linkedlist(有图+例子)


你可能感兴趣的:(Leetcode ☞ 287. Find the Duplicate Number ☆)