• 寻找重复数(力扣第287题)


    287.寻找重复数

    ​ 给定一个包含n+1个整数的数组 nums,其数字都在1到n之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

    示例 1:

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

    示例 2:

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

    说明:

    不能更改原数组(假设数组是只读的)。
    只能使用额外的 O(1) 的空间。
    时间复杂度小于 O(n2) 。
    数组中只有一个重复的数字,但它可能不止重复出现一次。

    分析:

    ​ 该题要求相当苛刻,数组是只读的,不能使用额外空间,那么借助哈希表的方法也就不行了,时间复杂度则要求不能使用暴力法,数组中只有一个重复的数字,但是这个重复出现的数字可能不止重复一次。

    ​ 一开始做起这个题也没有头绪,所以也参考了其他人的解法,主要使用的是二分法和快慢指针。

    ​ (1)二分法

    ​ 这个数组乍一看,并不是一个有序数组,并不能直接使用二分法,但是经过一些处理,就能造出一个升序数组出来。首先明确一点,该数组一共有n+1个元素,这些元素值都在1-n之间,那么我们可以定义一个数组count[i],用于记录给定数组中小于等于i的元素个数,其中1=<i<=n。同时定义一个变量target,表示数组中重复的元素。

    ​ 对于原数组中在[1,targrt-1]区间内的元素来说,其满足 count[i] <=i;

    ​ 对于原数组中在[target,n]区间内的元素来说,其满足 count[i] > i;

    ​ 解释一下为啥是count[i] <= i,如果原数组中重复的元素只出现两次,因为原数组的大小是n+1,那么1-n这个范围内的所有元素都会出现,所以此时count[i] ==i;如果原数组中重复出现的元素出现的次数大于两次,那么1-n这个范围内有的元素并不会出现,不会出现的元素可被认为由重复元素替代了,对于不会出现的元素分为两种情况:

    ​ (1)没出现的元素i位于[1,targrt-1]内,那么[i+1,targrt-1]区间内的元素k对应的count值应该都减去1,此时就是count[k] < k了;

    ​ (2)没出现的元素j位于[target,n]内,那么[target,j-1]区间内的元素k对应的count值都应该加上1,此时也满足count[k]>k了;

    ​ 比如,上面的示例2,[3,1,3,4,2],其count与nums值的对应关系如下:

    nums 1 2 3 4
    count 1 2 4 5

    ​ 我们要找的就是上面这个表中,第一个count[i] > i的那个值,这个值就是重复值。

    ​ 相当于原始数组的元素值作为count值的索引(1-n),然后对count数组进行二分查找,寻找第一个count值大于其索引值的的那个元素,这元素的count索引值就是最终的结果。

    实现代码:

    public int findDuplicate2(int[] nums) {
    
        int n = nums.length;
        int left = 1;
        int right = nums.length-1;
        while (left < right){
    
            int mid = (right + left) / 2;
            int count = 0;
    
            for (int i = 0; i < n; i++) {
                if (nums[i] <= mid){
                    count++;
                }
            }
            if ( count <= mid ){
                left = mid + 1;
            }else {
                right = mid;
            }
        }
        return left;
    }
    

    参考文档:

    https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 数组与矩阵.md#5-有序矩阵的-kth-element

    https://leetcode-cn.com/problems/find-the-duplicate-number/solution/kuai-man-zhi-zhen-de-jie-shi-cong-damien_undoxie-d/

  • 相关阅读:
    Java编程思想学习(三)----第三章:操作符
    mybatis入门
    responsebody和requestbody的使用
    一个Interface 继承多个Interface 的总结
    requirejs中Shims使用说明
    java 中解析json步骤
    @transient加在属性前的作用
    实现serializable接口的作用
    springmvc源码解析-初始化
    @RequestMapping注解详解
  • 原文地址:https://www.cnblogs.com/yxym2016/p/14022664.html
Copyright © 2020-2023  润新知