Leetcode_026(Array)

本文探讨了删除有序数组中重复元素的多种方法,包括使用额外数据结构如map、双指针技巧等,并对比了各种方法的空间及时间复杂度。

原题:删除有序数组中的重复项

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值。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值