题目:
在一个长度为n的数组里的所有数字都在0到n-1的范围内。
数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。
请找出数组中任意一个重复的数字。
方法1:暴力嵌套两次循环,时间复杂度O(n^2),空间复杂度O(1)
bool weatherRepeat(vector<int> num){
for(int i = 0; i < num.size(); ++i){
for(int j = i + 1; j < num.size(); ++j){
if(num[i] == num[j]){
return true;
}
}
}
return false;
}
方法2:标记法,对出现过的数字使用一种数据结构存放其出现过的次数,如果超过一次返回true
时间复杂度O(n),空间复杂度O(n),可以使用map,也可以使用set,也可以用数组。关于map和set将在下一篇中具体来研究。这里使用一个vector<int> 来实现。
bool weatherRepeat(vector<int> num){
vector<int> a(num.size(), 0);
for(int i = 0; i < num.size(); ++i){
a[num[i]]++;
if(a[num[i]] == 2){
return true;
}
}
return false;
}
方法3:因为所有的数字都是在0 - n-1的范围内,所以在将数组排序之后,如果不存在重复的数字,则是按照0 - n-1依次递增的,所以利用这个特性,循环一次,如果num[i]与num[num[i]]的值相等,则返回true,不等则将num[i] 与 num[num[i]]的值进行交换。此方法的时间复杂度为O(n),空间复杂度为O(1)。
bool weatherRepeat(vector<int>& num){
for(int i = 0; i < num.size(); ++i){
if(num[i] != i){
int temp = num[i];
if(num[i] == num[temp]){
return true;
}else{
int tp = num[i];
num[i] = num[temp];
num[temp] = tp;
}
}
}
return false;
}
在leetcode上有一道类似的题目
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
Input: [4,3,2,7,8,2,3,1] Output: [5,6]
class Solution {
public:
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> a;
for(int i = 0; i < nums.size(); ++i){
int m = abs(nums[i]) - 1;
nums[m] = nums[m] > 0 ? -nums[m] : nums[m];
}
for(int i = 0; i < nums.size(); ++i){
if(nums[i] > 0){
a.push_back(i + 1);
}
}
return a;
}
};
用这个思路,也可以解答上面那个题,只不过时间复杂度更多点。O(2N)