原题:删除有序数组中的重复项
1、自解(暴力法):
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0){
return 0;
}//if
int location, count;
vector <int> mygoal;
vector<int>::iterator myir;
location = 0;
count = 1;
mygoal.push_back(nums[0]);
myir = nums.begin();
for (int i = 1; i < nums.size(); ++i) {
if (mygoal[location] == nums[i]){
continue;
} else{
mygoal.push_back(nums[i]);
count++;
location++;
}
}//for
nums.clear();
for (int i = 0; i < mygoal.size(); ++i) {
nums.push_back(mygoal[i]);
}//for
return count;
}//removeDuplicates
2、自解(map暴力法):
int removeDuplicates(vector<int>& nums){
map<int,int> mymap;
for (int i = 0; i < nums.size(); ++i) {
if (mymap.find(nums[i]) != mymap.end()){
continue;
} else{
mymap.insert(pair<int,int>(nums[i],1));
}
}//for
nums.clear();
for(auto it: mymap){
nums.push_back(it.first);
}
return mymap.size();
}//removeDuplicates
3、评论解(快速方法,感觉是mvp了):
int removeDuplicates(vector<int>& nums) {
if (nums.size() < 2) return nums.size();
int j = 0;
for (int i = 1; i < nums.size(); i++)
if (nums[j] != nums[i]) nums[++j] = nums[i];
return ++j;
}
4、自写抄官方题解(比较经典的双指针思想):
int removeDuplicates(vector<int>& nums) {
if (nums.size() == 0){
return 0;
} else{
int fast, slow;
fast = 1;
slow = 1;
for (int i = 1; i < nums.size(); ++i) {
if (nums[fast] == nums[fast-1]){
fast++;//快走
} else{
nums[slow++] = nums[fast++];//快慢一起走,重初始化
}
}
return slow++;//角标从0开始,数组大小补全
}
}
Summary:
这道题不算难题,主要问题如何优化空间复杂度。初版方法代码有些长,对于这个简答题有些不应该了。之后自己总结了一下写了一个调用map的短版本,两者复杂度相差不大,估计和调用了clear函数有关。
1、对于初代方法,我创建了新的vector来放不同元素的新数组,且最后由于要返回引用,我将原引用vector清空来重新存(初始化)放我新创建的数组,这个类似copy的过程涉及空间的销毁和开辟,因此空间复杂度更高,时间复杂度循环了多次n,因此有2n的复杂度,难受。
2、由于对自己编写代码简洁度不够高的不满,我用复习了的map写了一个较短版本。不过不可避免的是map键值的初始化也要创建新的空间,而其他clear操作和push_back操作是和初代方法差不多的。总结来说是多利用了一点空间,降低了代码量。这一切还是要由于vector没有find函数。
3、这个快速方法看到的第一眼就惊了,我超,这也太简便了。读了几遍代码后给这个方法冠以了"Make ends meet"方法。也怪我没好好读题,因为返回的容器大小可以不正好,只要随其返回正常的顺序不重复子集大小就好。这个func的简便之处在于 提高了双指针方法与函数的耦合性 。即双指针方法中的 fast 和这里的 i 是等价的,巧妙减少代码量,不过效率是一样的。
4、典型的双指针,slow负责不重复子集的初始化,fast负责遍历整个数组。就是这个思想,不用clear。
最后,这里有一点需要注意,读题的时候细心,或者说这道题本就有一些地方模棱两可。而这个点也恰好是时空复杂度的关键点。这道题中的矛盾点就在于返回数组大小是否和返回数字的值是一样的。后面两个参考方法都表明不一定一样。即引用数组大小>=返回的int值。
本文探讨了删除有序数组中重复元素的多种方法,包括使用额外数据结构如map、双指针技巧等,并对比了各种方法的空间及时间复杂度。
938

被折叠的 条评论
为什么被折叠?



