剑指 Offer 03. 数组中重复的数字模拟哈希表解法。
题目描述找出数组中重复的数字。
在一个长度为 n (2 <= n <= 100000)的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
样例
思路输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
我们知道长度为n,角标即为
[
0
,
n
−
1
]
left[0,n-1right]
[0,n−1]。而数据范围恰好也是
[
0
,
n
−
1
]
left[0,n-1right]
[0,n−1]。我们可以直接用原数组来记录数据出现的次数。
当某数字nums[i]第一次出现时,将以其为角标的元素nums[nums[i]]变为负。当向后读取时出现nums[nums[i]] < 0的情况,则证明nums[i]已经出现过。需要注意的是当我们访问nums[i]为角标的元素时,nums[i]可能已经被改为负数,访问以原值为角标的位置需要将其取绝对值nums[abs(nums[i])]。
由于涉及到cpp里INT型没有+0,-0问题,题目中说必有重复元素,如果遍历结束仍然没有找到,则重复的元素是0,比如以下样例。
上述说明有点过于抽象,以测试样例为例。
| 状态 | nums[0] | nums[1] | nums[2] | nums[3] | nums[4] | nums[5] | nums[6] |
|---|---|---|---|---|---|---|---|
| 初始值 | 2 | 3 | 1 | 0 | 2 | 5 | 3 |
| i=0 | 2 | 3 | -1 | 0 | 2 | 5 | 3 |
| i=1 | 2 | 3 | -1 | -0 | 2 | 5 | 3 |
| i=2 | 2 | -3 | -1 | -0 | 2 | 5 | 3 |
| i=3 | -2 | -3 | -1 | -0 | 2 | 5 | 3 |
| i=4 | -2 | -3 | -1 | ||||
| i=5 | |||||||
| i=6 |
- i = 0时,nums[i] = 2,此时以2的绝对值(取绝对值是为了防止遍历过程中数组中元素已经被取负,导致非法访问)为角标的位置来记录2出现的次数,nums[abs(nums[i])] = nums[2]取负。
- i = 1时,nums[i] = 3,nums[abs(nums[i])] = nums[3]取负(由于没有+0,-0看不出变化)。
- i = 2时,nums[i] = -1,nums[abs(nums[i])] = nums[1]取负。
- i = 3时,nums[i] = 0,nums[abs(nums[i])] = nums[0]取负。
- i = 4时,nums[i] = 2,nums[abs(nums[i])] = nums[2]此时已经为负数(证明其角标2代表的元素2出现过),故其是重复元素,返回。
class Solution {
public:
int findRepeatNumber(vector& nums) {
for(auto& num:nums) {
if(nums[abs(num)] < 0) return abs(num);
nums[abs(num)] *= -1;
}
return 0;
}
};
运行结果
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


![[剑指 Offer 03. 数组中重复的数字] 模拟哈希表解法 [剑指 Offer 03. 数组中重复的数字] 模拟哈希表解法](http://www.mshxw.com/aiimages/31/879073.png)
