zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    每天一个linux命令(40):wc命令
    每天一个linux命令(39):grep 命令
    每天一个linux命令(38):cal 命令
    每天一个linux命令(37):date命令
    每天一个linux命令(36):diff 命令
    每天一个linux命令(35):ln 命令
    [android] Activity 的生命周期 以及横屏竖屏切换时 Activity 的状态变化
    Android onConfigurationChanged 不执行
    faster-rcnn anchor 介绍
    Faster-rcnn centos tensorflow
  • 原文地址:https://www.cnblogs.com/wltree/p/15384287.html
Copyright © 2011-2022 走看看