剑指 Offer 03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
解题思路:
这题为了降低时间复杂度,我们可以采用原地置换的方式,方法的思维和一个萝卜一个坑比较类似
- 首先,我们来看没有重复数字的数组
nums: 3 1 0 2
nums[i] 3 1 0 2 萝卜
i 0 1 2 3 坑
0号坑说:我不要三号萝卜,我要自己的0号萝卜,因此请求和第三号坑的萝卜进行交换,然后变成这样
nums[i] 2 1 0 3 萝卜
i 0 1 2 3 坑
0号坑发现自己还没有找到萝卜,于是又请求与二号坑的萝卜进行交换
nums[i] 0 1 2 3 萝卜
i 0 1 2 3 坑
这样,刚好所有的萝卜与坑都是一一对应的,因此退出循环
- 然后,我们来看有重复数字的数组
nums: 1 2 3 2
nums[i] 1 2 3 2 萝卜
i 0 1 2 3 坑
同样的,0号坑不要1号萝卜,请求与1号坑交换
nums[i] 2 1 3 2 萝卜
i 0 1 2 3 坑
0号坑不要2号萝卜,请求与2号坑交换
nums[i] 3 1 2 2 萝卜
i 0 1 2 3 坑
0号坑不要3号萝卜,请求与3号坑交换
nums[i] 2 1 2 3 萝卜
i 0 1 2 3 坑
0号坑不要2号萝卜,请求与2号坑交换,但是发现2号坑也是2号萝卜,交换没有意义,直接退出循环,返回当前值(说明出现了重复元素)
时间复杂度O(n),空间复杂度O(1)
AC代码
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int temp;
for (int i = 0; i < nums.size(); i++){
while (nums[i] != i){
//发现自己的萝卜和要请求交换的坑的萝卜相同,说明有重复数字出现
if(nums[i] == nums[nums[i]]){
return nums[i];
}
//交换萝卜
temp = nums[i];
nums[i] = nums[temp];
nums[temp] = temp;
}
}
//所有的数字都在自己应该在的位置上,说明没有重复元素
return -1;
}
};
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!