zoukankan      html  css  js  c++  java
  • [LeetCode]103. 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.

    解法:使用鸽巢原理可以很简单的证明。注意Note的第四点,有且仅有一个重复的数字,但是这个重复的数字可能出现两次以上。这说明这n+1个数并不是一定包含了[1,n]中的每个数。开始时没注意到这点,用

    return accumulate(nums.begin(), nums.end(), 0) - ((nums.size() - 1) * nums.size() >> 1);

    结果显然错误。因为不能修改输入数组且空间复杂度要求为O(1),所以不能用排序,也不能使用HashTable。因为时间复杂度必须低于O(n^2),因此不能使用暴力破解法。

    //修改输入数组的排序方法
    class Solution {
    public:
        int findDuplicate(vector<int>& nums) {
            int n = nums.size(), i = 0;
            sort(nums.begin(), nums.end());
            for(; i < n - 1; ++i) {
                if(nums[i] == nums[i + 1]) break;
            }
            return nums[i];
        }
    };
    //额外O(n)空间的Hash方法
    class Solution {
    public:
        int findDuplicate(vector<int>& nums) {
            int n = nums.size(), i = 0;
            vector<int> cnt(n, 0);
            for (; i < n; ++i) {
                if (++cnt[nums[i]] > 1) break;
            }
            return nums[i];
        }
    };
    //O(n^2)时间的暴力破解法
    class Solution {
    public:
        int findDuplicate(vector<int>& nums) {
            int n = nums.size(), i = 0, j = 0;
            for (i = 0; i < n - 1; ++i) {
                for (j = i + 1; j < n; ++j) {
                    if (nums[i] == nums[j]) break;
                }
                if (j != n && nums[i] == nums[j]) break;
            }
            return nums[i];
        }
    };

    考虑到这n+1个数是在有序的[1,n]中选取的,因此可以考虑在[1,n]中使用二分查找,即在[1,n]中每次折半选出一个数mid,遍历输入数组统计小于等于mid的元素个数cnt。如果cnt>mid,说明重复值在[1,mid-1]之间,否则在[mid+1,n]之间。时间复杂度O(nlogn),空间复杂度O(1)。

    class Solution {
    public:
        int findDuplicate(vector<int>& nums) {
            int n = nums.size(), left = 1, right = n - 1;
            while (left <= right) {
                int mid = (left + right) >> 1, cnt = 0;
                for (int i = 0; i < n; ++i) {
                    if (mid >= nums[i]) ++cnt;
                }
                if (cnt > mid) right = mid - 1;
                else left = mid + 1;
            }
            return left;
        }
    };
  • 相关阅读:
    MVC 自定义异常过滤特性
    写一个左中右布局占满屏幕,其中左右两块是固定宽度200,中间自适应宽度, 要求先加载中间块,请写出结构及样式。
    请写出jQuery绑定事件的方法,不少于两种
    用js写个原生的ajax过程
    link和@import的区别
    attribute和property的区别是什么?
    请简要描述margin重复问题,及解决方式
    display:none;与visibility:hidden;的区别
    web标准以及w3c标准
    css优先级
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5032243.html
Copyright © 2011-2022 走看看