剑指 Offer 03. 数组中重复的数字
方法一:利用空间换时间。哈希表
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
vector<int> hashNum;
int ans;
int len = nums.size();
hashNum.resize(len,0);
for(int i=0;i<len;i++){
if(hashNum[nums[i]] == 0){
hashNum[nums[i]]++;
}else{
ans = nums[i];
break;
}
}
return ans;
}
};
解法二:原地置换
我们注意到数组中数字都在0~n-1的范围内。如果这个数组中没有重复的数字,那么当数组排序之后数字i将出现在下标为i的位置。
由于数组中有重复的数字,有些位置可能存在多个数字,同时有些位置可能没有数字。我们利用这个规律来查重。
以数组{2,3,1,0,2,5,3}为例来分析找到重复数字的步骤。
数组的第0个数字(从0开始计数,和数组的下标保持一致)是2,
那么我们检查第2个数字。如果第2个数字也是2,那么查重成功。否则,我们交换这两个下标的数字。(相当于排序,至少数字2放在了大概正确的位置)。
经过这样重复操作,有一部分已经有序,往后继续检索(操作),那么终究会查出来重复的数字。
代码如下:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int ans;
int len = nums.size();
int temp,j;
for(int i=0;i<len;i++){
while(nums[i]!=i){
j = nums[i];
if(nums[j] == j){
ans = j;
return j;
}
temp = nums[j];
nums[j] = j;
nums[i] = temp;
}
}
return ans;
}
};
复杂度分析:
代码中尽管有一个两重循环,但是每个数字最多只要交换两次就能找到属于它自己的位置,因此总的时间复杂度是O(n)。另外,所有操作步骤都是在输入数组上进行的,空间复杂度为常熟级别的O(1)。