題目
題目鏈接
Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in O(n) runtime?
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[2,3]
給定一個數組的整數,其中數組中的元素滿足1 ≤ a[i] ≤ n ,n是數組的元素個數。一些元素出現了兩次,而其它元素只出現了一次。
找出那些出現了兩次的元素。要求沒有占用額外的空間而且時間復雜性為 O(n) 。
例如:
輸入:
[4,3,2,7,8,2,3,1]
輸出:
[2,3]
思路
(不想看其它思路的可以直接跳到第三個)
其實本來一開始想到的實現方法是hash table的,但是如各位所知,hash table對空間還是有要求的,因此其實不符合題意,權當寫着玩了。hash table的solution如下,runtime一般:
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
int m=nums.size(),n;
int s[m];
vector<int> ans;
memset(s,0,m*4);
for(int i=0;i<m;i++)
{
n=nums[i]-1;
s[n]++;
}
for(int i=0;i<m;i++)
if(s[i]>1) ans.push_back(i+1);
return ans;
}
};
第二個想法,先排序,再判斷。runtime比較差,但空間占用少。
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
int m=nums.size(),n;
vector<int> ans;
stable_sort(nums.begin(),nums.end(),[](const int& x,const int& y){return x<y;});
for(int i=0;i<m;i++)
if(nums[i]==nums[i+1]) {ans.push_back(nums[i]);i++;}
return ans;
}
};
第三個想法,先歸位,沒在位置上的就是重復的數字。這個solution比之前的兩個runtime表現都要好。
class Solution {
public:
vector<int> findDuplicates(vector<int>& nums) {
int m=nums.size(),n;
vector<int> ans;
for(int i=0;i<m;)
if(nums[nums[i]-1]!=nums[i])
swap(nums[i],nums[nums[i]-1]);
else i++;
for(int i=0;i<m;i++)
if(nums[i]!=i+1) ans.push_back(nums[i]);
return ans;
}
};