剑指 Offer 03. 数组中重复的数字#
问题描述#
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例 1:
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
限制:
2 <= n <= 100000
解题思路#
方法一:哈希表标记#
用哈希表标记出现过的数字。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
时间复杂度:\(\mathcal{O}(n)\)
空间复杂度:\(\mathcal{O}(n)\)
方法二:数组标记#
因为数字的范围已经给定了,所以可以直接使用数组来标记出现过的数字。
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 |
|
时间复杂度:\(\mathcal{O}(n)\)
空间复杂度:\(\mathcal{O}(n)\)
方法三:用正负号来标记数字#
对于每个数字,我们将这个数字作为下标索引位置上的数字变为相反数,这样下次这个数字出现时,我们就可以根据该位置上数字的符号来判断了。
因为数字 \(0\) 的存在,导致正负号失去作用,所以首先对原数组中的每个数都增加 \(1\),遍历时再减去 \(1\) 即可。
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
时间复杂度:\(\mathcal{O}(n)\)
空间复杂度:\(\mathcal{O}(1)\)
方法四:索引标记#
类似方法三,只不过我们是将数字交换回它所在的索引,使得 \(\texttt{nums}[i]=i\),如果下次遇到 \(\texttt{nums}[i]!=i\) 但是 \(\texttt{nums}[\texttt{nums}[i]]=\texttt{nums}[i]\),就说明 \(\texttt{nums}[i]\) 重复了。
1 2 3 4 5 6 7 8 9 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
时间复杂度:\(\mathcal{O}(n)\)
空间复杂度:\(\mathcal{O}(1)\)