[剑指Offer-03][简单] 数组中重复的数字

题目描述

剑指 Offer 03. 数组中重复的数字

找出数组中重复的数字。

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

示例 1:

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

限制:

  • 2 <= n <= 100000

解题思路

原地哈希

这道题如果加上一个要求空间复杂度O(1)O(1), 整体就有难度了. 注意, 题目强调了, 长度为n的数组其中的元素都是0 ~ n-1范围内的. 因此, 将数字i送回其对应的位置就好, 使得nums[i] = i, 相当于完成了原地的哈希操作.

具体细节, 我们需要从位置0开始, 先将数字0放置回索引为0的位置, 这个过程伴随着交换, 将0索引位置上数字nums[0]放置到索引nums[0]的位置, 对应位置的数字num[nums[0]]被交换到0索引的位置. 持续这种交换, 直到我们发现将此时的数字num[0]放置到对应索引num[0]的位置时, 那个位置上的数字正是num[0], 说明这个数字重复了, 跳出返回这个数字.

如果0这个数字不存在与数组中, 我们在不断的交换过程中, 一定会遍历所有的数字, 直到遇到上面的情况, 即找到答案. 又因为长度为n的数组, 不包含0 ~ n-1中的某个数字, 则肯定有至少两个数字是重复的.

除了在交换过程中找到了重复数字, 还有一种情况下, 对0位置的操作将停止, 就是数字0已经归位. 这时我们需要探索下一个数字1. 重复这个过程, 直到交换过程中遇到了相同的数字.

因此, 这是双层的while嵌套.

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        for i in range(len(nums)):
            while i != nums[i]:
                if nums[i] == nums[nums[i]]:
                    return nums[i]
                nums[nums[i]], nums[i] = nums[i], nums[nums[i]]

最后更新于