寻找重复数-LeetCode287

寻找重复数-LeetCode287,第1张

一、题目描述

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

注意!!!   :你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

示例一:

输入:nums = [1,3,4,2,2]
输出:2

二、解题思路(这道题的解题思路很难想到,以前做的题从来没有碰到过。)

(1)题目有明确要求:设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。这就告诉我们,不能对nums数组进行排序,不能使用额外的辅助数组,所以我们就只能对原数组进行遍历(没限制时间复杂度),在遍历的过程中找到原问题的解

(2)利用二分查找法。

1)二分查找需要确定区间的左右端点,且能有某个性质,能在区间对半分后舍弃调其中一半的区间,在该题中,因为我们知道给定的数组中所有数的一个范围,也就是nums.length-1,利用这个性质,我们可以设置初始区间左右端点如下:

left=1 //表示所有数的最小

right=nums.length-1 //所有数的最大

所以该题中找的mid与普通二分法不同,该题中所找的mid就是所给数的范围的中间,而不用再取nums[mid]来在题中进行判断

2) 那么我们来怎么判断哪个区间该舍弃?哪个区间该留下呢?

我们定义 cnt[i] 表示nums 数组中小于等于i 的数有多少个,假设我们重复的数是 target,那么 [1,target−1]里的所有数满足 cnt[i]≤i,[target,n] 里的所有数满足 cnt[i]>i,具有单调性。以此就可以得知应舍弃掉哪个区间。例:

nums[i]={1,2,2,2,5,3},区间范围为[1,5](nums[i]共有6个数)

i12345
nums[i]14556

此题中target=2

[1,2):cnt[1]<=1

[2,5]:cnt[2]=4>=2,cnt[3]=5>=3,cnt[4]=5>=4;cnt[5]=6>=5

结论成立

三、代码示例

/**
* 该题涉及nums数组中数的范围,是一个突破口
 * 二分查找应用题型:target左边范围的数和右边范围的数有明显区别,且以target为界限划分的小区间也具有前面的性质
*/

//以重复的数target为界:小于target的数的数量<=i;大于等于target的数的数量>i
class Solution51 {
    public int findDuplicate(int[] nums) {
        int n = nums.length;
        //l、r指针是指向的nums的范围,而不是nums中的数的下标
        //如:nums={1,3,2,2,2,5}:其范围是1,2,3,4,5,而l指向1,r指向5,所以mid为3
        int l = 1, r = n - 1, ans = -1;
        //为什么循环条件为:l<=r?以重复的数target为界:小于target的数的数量<=i;大于等于target的数的数量>i,
        //所以任何时候确定l、r进而确定的区间必定是向target靠拢的,直至l>r
        while (l <= r) {
            int mid = (l + r) >> 1;
            int cnt = 0;
            for (int i = 0; i < n; ++i) {
                if (nums[i] <= mid) {
                    cnt++;
                }
            }
            //如果当前小于中间的数的数量比中间的数小,说明重复的数是比中间的数大的,且重复的数可能占用了[1,mid]中的数的位置
            if (cnt <= mid) {
                l = mid + 1;
            } else {
                //如果当前大于中间的数的数量比中间的数大,说明重复的数是比中间的数小的
                r = mid - 1;
                ans = mid;
            }
        }
        return ans;
    }
}

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/742220.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存