题目要求:
Do it in O(n) time complexity.
Do it in O(nlogn) time without extra space.
解法1:用unordered_set。O(n)复杂度。
注意:
- 这里是反向双指针。
- 若i对应元素已经存在于set中,则将j和i元素对调。j–。这里如果j对应元素也已经存在也没关系,因为while()又会继续检查i对应元素的。
int deduplication(vector<int> &nums) {
unordered_set<int> s;
int i=0, j=nums.size()-1;
int count=0;
while(i<=j) { //注意这里是i<=j
if (s.count(nums[i])!=0) {
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
count++;
j--;
}
else {
s.insert(nums[i]);
i++;
}
}
return nums.size()-count;
}
解法2:类似解法1。也是O(n)复杂度。
注意:
- 这里是反向双指针
- 和解法1不同的是这里p1和p2都动。先看p1的元素是否已存在于set中,若否,则加入set,否则看p2的元素是不是已经存在于set中。若是,则while()循环p–,直到直到p2的元素是一个新元素或p2<p1为止。若p1<p2,则将p2元素加入set,同时p1和p2元素交换。
class Solution {
public:
/**
* @param nums: an array of integers
* @return: the number of unique integers
*/
int deduplication(vector<int> &nums) {
int n = nums.size();
if (n <= 1) return n;
unordered_set<int> us;
int count = 0;
int p1 = 0, p2 = n - 1;
while(p1 <= p2) {
if (us.find(nums[p1]) == us.end()) {
us.insert(nums[p1]);
count++;
p1++;
} else {
while(us.find(nums[p2]) != us.end() && (p1 <= p2)) {
p2--;
}
if (p1 < p2) {
us.insert(nums[p2]);
swap(nums[p1], nums[p2]);
count++;
p1++; p2--;
}
}
}
return count;
}
};
解法3:先统统往unordered_set里面丢,最后遍历它,放到num[]开头即可。
这里不需要用到双指针,但要走2次循环。
int deduplication(vector<int> &nums) {
unordered_set<int> s;
for (int i=0; i<nums.size(); ++i)
s.insert(nums[i]);
int index=0;
for (auto i : s)
nums[index++]=i;
return index;
}
解法4:**排序后用双指针。一个快指针一直往前走,慢指针先不动。当快指针发现它指向的数和慢指针不一样,就把该数丢给慢指针的后一个位置。慢指针++。最后返回慢指针的值+1。**这个思路很不错。
注意这里是同向双指针!
int deduplication(vector<int> &nums) {
if (nums.size()==0) return 0;
sort(nums.begin(), nums.end());
int i=0, j=0;
while(i<nums.size()) {
if (nums[i]!=nums[j]) {
nums[++j]=nums[i];
}
++i;
}
return j+1;
}