> For the complete documentation index, see [llms.txt](https://kerasnoone.gitbook.io/garnet/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerasnoone.gitbook.io/garnet/suan-fa/shu-zu/jian-zhi-offer03-shu-zu-zhong-zhong-fu-de-shu-zi.md).

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

## 题目描述

[剑指 Offer 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(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`嵌套.

```python
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]]
```
