27. 移除元素

题目:https://leetcode-cn.com/problems/remove-element/

自己写的代码(C++)

 1 C++ 2 
 3 class Solution {
 4 public:
 5     int removeElement(vector<int>& nums, int val) {
 6         int len = 0;
 7         int i = 0, j = nums.size() - 1;
 8         while ( i <= j ){
 9             if (nums[i] == val && nums[j] != val){
10                 int tmp = nums[i];
11                 nums[i] = nums[j];
12                 nums[j] = tmp;
13                 len++;
14                 i++;
15                 j--;
16             }
17             if (nums[i] != val) i++;
18             if (nums[j] == val){
19                 len++;
20                 j--;
21             }
22         }
23         return nums.size() - len;
24     }
25 };

 题目挺简单的,这是第一次使用C++STL中的容器vector。

1、C++ vector的初始化: https://blog.csdn.net/qq_40147449/article/details/87892312?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

2、vector作为参数的三种传参方式:https://www.cnblogs.com/xiaoxi666/p/6843211.html

c++中常用的vector容器作为参数时,有三种传参方式,分别如下(为说明问题,用二维vector):

  • function1(std::vector<std::vector<int> > vec),传值
  • function2(std::vector<std::vector<int> >& vec),传引用
  • function3(std::vector<std::vector<int> >* vec),传指针

注意,三种方式分别有对应的const形式,不在此讨论。

三种方式对应的调用形式分别为:

  • function1(vec),传入值
  • function2(vec),传入引用
  • function3(&vec),传入地址

三种方式的效果分别为:

  • 会发生拷贝构造
  • 不会发生拷贝构造
  • 不会发生拷贝构造

自己写的代码(JAVA)

 1 JAVA:
 2 
 3 class Solution {
 4     public int removeElement(int[] nums, int val) {
 5     int len = 0;
 6         int i = 0, j = nums.length - 1;
 7         while ( i <= j ){
 8             if (nums[i] == val && nums[j] != val){
 9                 int tmp = nums[i];
10                 nums[i] = nums[j];
11                 nums[j] = tmp;
12                 len++;
13                 i++;
14                 j--;
15             }
16             else if (nums[i] != val) i++;
17             else if (nums[j] == val){
18                 len++;
19                 j--;
20             }
21 
22         }
23         return nums.length-len;
24     }
25 }

 

官方:https://leetcode-cn.com/problems/remove-element/solution/yi-chu-yuan-su-by-leetcode-solution-svxi/

方法一:双指针
由于题目要求删除数组中等于 val 的元素,因此输出数组的长度一定小于等于输入数组的长度,我们可以把输出的数组直接写在输入数组上。可以使用双指针:右指针 right 指向当前将要处理的元素,左指针left 指向下一个将要赋值的位置。
如果右指针指向的元素不等于 val,它一定是输出数组的一个元素,我们就将右指针指向的元素复制到左指针位置,然后将左右指针同时右移;
如果右指针指向的元素等于 val,它不能在输出数组里,此时左指针不动,右指针右移一位。
整个过程保持不变的性质是:区间 [0,left) 中的元素都不等于 val。当左右指针遍历完输入数组以后,left 的值就是输出数组的长度。
这样的算法在最坏情况下(输入数组中没有元素等于val),左右指针各遍历了数组一次。

 1 C++ 2 
 3 class Solution {
 4 public:
 5     int removeElement(vector<int>& nums, int val) {
 6         int n = nums.size();
 7         int left = 0;
 8         for (int right = 0; right < n; right++) {
 9             if (nums[right] != val) {
10                 nums[left] = nums[right];
11                 left++;
12             }
13         }
14         return left;
15     }
16 };

方法二:双指针优化(和我的方法差不多)
如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4],同样满足题目要求。这个优化在序列中 val 元素的数量较少时非常有效。
实现方面,我们依然使用双指针,两个指针初始时分别位于数组的首尾,向中间移动遍历该序列。
算法
如果左指针left 指向的元素等于 val,此时将右指针 right 指向的元素复制到左指针 left 的位置,然后右指针right 左移一位。如果赋值过来的元素恰好也等于 val,可以继续把右指针 right 指向的元素的值赋值过来(左指针left 指向的等于 val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于 val 为止。
当左指针 left 和右指针 right 重合的时候,左右指针遍历完数组中所有的元素。
这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。

 1 C++:
 2 
 3 class Solution {
 4 public:
 5     int removeElement(vector<int>& nums, int val) {
 6         int left = 0, right = nums.size();
 7         while (left < right) {
 8             if (nums[left] == val) {
 9                 nums[left] = nums[right - 1];
10                 right--;
11             } else {
12                 left++;
13             }
14         }
15         return left;
16     }
17 };

 

代码随想录:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html#%E6%80%9D%E8%B7%AF

该方法与官网的方法一差不多。

posted @ 2021-10-09 10:06  wltree  阅读(35)  评论(0编辑  收藏  举报