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;
        }
    };
  • 相关阅读:
    flume采集log4j日志到kafka
    解决spring 事务管理默认不支持SQLException等运行时异常
    基于黑名单的xss过滤器
    VMware创建Linux虚拟机并安装CentOS(三)
    dubbo 常见错误
    Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)
    zookeeper工作原理、安装配置、工具命令简介
    VMware创建Linux虚拟机并安装CentOS(二)
    NSPredicate谓词
    IOS网络请求之NSURLSession使用详解
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5032243.html
Copyright © 2011-2022 走看看