面试题03. 数组中重复的数字

https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

找出数组中重复的数字。

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

示例 1:

输入:[2, 3, 1, 0, 2, 5, 3]

输出:2 或 3

限制:

2 <= n <= 100000


方法一: 哈希表

小技巧

遍历数组时判断是否在哈希表中存在,如果存在就找到了一个重复的数字。

此法需要额外的空间开销

备注

  • 时间复杂度:O(n)

  • 空间复杂度:O(n)

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        a = {}
        for n in nums:
            if n in a:
                return n
            a[n] = n

方法二: 下标定位法

小技巧

如题描述,长度为 n 的数组,数字都在 0~n-1 的范围内,如果没有重复的数字, 则数字 i 应该出现在 nums[i] 位置,即 num[i] = i;

假设数组长度为 7,则数字范围是 [0, 6]。

我们有 7 个篮子,上面的编号为依次为 0 ~ 6,每个篮子里面有个球,球上面有编号,编号范围是 [0, 6]。

我们从第一个篮子开始检验,如果篮子里面球的编号和篮子编号一致,检验合格; 如果发现篮子里面球的编号和篮子编号不一致,我们怀疑 当前这个球本该在这个篮子的球 偷偷换了位置,让当前这个球滚回与其编号一致的篮子,并把在它篮子里的球换回来; 如果换回来的球与篮子编号还不一致,同理,继续更换;如果在更换过程中,让当前球滚去其该再的位置时,发现已经有相同的球在那了,我们就找到了 重复的数字

此法改变了原数组

备注

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for position, ball in enumerate(nums):
            # 篮子编号与球不一致,让球滚回其该再的位置
            while position != ball:
                #  滚回去发现,球的位置上已经有了一个自己,发现重复元素
                if nums[ball] == ball:
                    return ball
                nums[position], nums[ball] = nums[ball], nums[position]