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;
        }
    };
  • 相关阅读:
    php字符串处理(邮件处理)
    phpstrtotime()对于31日求上个月有问题
    .net中linkbutton增加js验证
    excel 常用属性
    回车换行符总结
    视图增加自增id
    SQL优化索引、查询优化及分页算法方案
    js,cookies做悬浮购物车
    Server Application Unavailable出现的原因及解决方案集锦
    asp(javascript)中request.form("a").count 在ie6中总是为0
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5032243.html
Copyright © 2011-2022 走看看