数组中重复的数字|刷题打卡

352 阅读2分钟

掘金团队号上线,助你 Offer 临门! 点击 查看详情

一、题目描述

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例:

输入

[2, 3, 1, 0, 2, 5, 3]

输出

2 或 3 

限制

2 <= n <= 100000

二、思路分析

我的思路

题目有点小问题,如果没有重复的返回啥?这里暂时返回-1;

  1. 最先思路肯定就是一个HashSet,然后不断的往里面塞和判断,这样就是空间换时间(直接的方法有很多:排序,循环去判断等)
  2. 后面想起了使用亦或来做,但是亦或其实不是这个场景的,想错了。(主要是印象中之前中好像有类似的题目是用亦或去做的)
  3. 最后想不出什么可以空间复杂度O(1) 时间复杂度还为O(n)的了,于是使用bitmap稍微降低一下空间复杂度(但是如果数字很多,重复数字又很靠前,那么申请bitmap的内存可能大于hashSet的内存)

最佳思路

长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内 (!!!! 我看漏了这最关键的信息,这样O(1)和O(n)就好找了) 也就是自身数组就可以当做那个bitmap,只要遇到不在自己索引位置的地方做交换和比较就行了。

三、AC 代码

我的写法:

public static int findRepeatNumber(int[] nums) {
    byte[] bitmap = new byte[nums.length];
    for (int num : nums) {
        byte b = bitmap[num];
        if (b == (byte) 1) {
            return b;
        } else {
            bitmap[num] = (byte) 1;
        }
    }
    return -1;
}

题解中清爽的写法

// 有意思的是,这个在跑的结果中显示比上面的内存占用还大 😂
public int findRepeatNumber2(int[] nums) {
    for (int index = 0; index < nums.length; index++) {
        int num = nums[index];
        if (nums[num] == num && index != num) {
            return num;
        } else {
            int tmp = nums[num];
            nums[num] = num;
            nums[index] = tmp;
        }
    }
    return -1;
}

四、总结

除了考虑对bitmap了解,还需要能针对不同场景,对bitmap活学活用。