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;
        }
    };
  • 相关阅读:
    阿里取消周报
    摇滚明星原则
    t
    B树、B+树索引算法原理(下)
    订单业务楼层化 view管理器和model管理器进行了model和view的全面封装处理 三端不得不在每个业务入口上线时约定好降级开关,于是代码中充满了各种各样的降级开关字段
    单元测试
    项目管理图 有任务分解、技术风险 风险预案
    CPU飙高,系统性能问题如何排查?

    如何让淘宝不卡顿? 读写比例 动态扩容 分布式化路线 mysql 优化
  • 原文地址:https://www.cnblogs.com/aprilcheny/p/5032243.html
Copyright © 2011-2022 走看看