【leetcode】27.移除数组元素

1、题目

2、错误分析

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //暴力解法,两层for循环
        int size=nums.size();
        for(int i=0;i<size;i++){
            if(nums[i]==val){
                for(int j=i;j<size-1;j++){
                    nums[j]=nums[j+1];//注意,这里不要超出数组索引范围
                }
                --i;//因为i++,所以还要判断i这个位置就需要--i;
                --size;
            }
        }
       return size; 
    }
};

(1)暴力解法,两个for循环,第一个for循环找到之后,第二个for循环将后面元素依次前移,时间复杂度是n2;时间复杂度:O(n^2);空间复杂度:O(1);

3、题解

采用快慢指针,示意图如下,来自代码随想录

(1)方法一:快慢指针,不会改变其相对位置(顺序),搬运元素次数=所有元素数-目标元素数;最后slow指向结尾元素;两个指针之差就是替换的目标元素数量;

(2)low指针指向当前要处理的元素,fast指针指向下一个将要赋值的元素,整个过程中保持不变的是,区间[0,low)的元素都不等于val,因此low就是数组长度;

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //采用快慢指针
        //int size=nums.size();不用size这个变量了
        int low=0;
        for(int fast=0;fast<nums.size();fast++){
            if(nums[fast]!=val){//在不相等的时候依次覆盖
                nums[low++]=nums[fast];
            }
        }
       return low;//注意,这里是Low,不是low+1
    }
};
// 时间复杂度:O(n),其中n为序列长度,最多遍历序列至多两次
// 空间复杂度:O(1),我们只需要常数空间保持若干变量

(3)方法二:双向指针,左右两个指针往中间走,左指针查找是value的位置,右指针指向不是value的位置,然后将右指针指向的元素搬到左指针,同时两指针往中间走,会改变数组的顺序(相对位置),但是可以搬运最少的数组元素;注意,最后搜寻结束时,左指针一定指向结尾的下一个元素位置;

顺着上一个区间的思考方式,[0,left)一直是正确的区间,保证此区间没有val值;right找到的val值相当于直接丢弃,需要保留的会赋给left指向的空间;一直到左右指针交汇;

方法二:避免了需要保留了元素的重复赋值操作;

【双向指针并未完全理解掌握,粘贴代码如下】,这个<=和<有点懵

/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:$O(n)$
* 空间复杂度:$O(1)$
*/
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int leftIndex = 0;
        int rightIndex = nums.size() - 1;
        while (leftIndex <= rightIndex) {
            // 找左边等于val的元素
            while (leftIndex <= rightIndex && nums[leftIndex] != val){
                ++leftIndex;
            }
            // 找右边不等于val的元素
            while (leftIndex <= rightIndex && nums[rightIndex] == val) {
                -- rightIndex;
            }
            // 将右边不等于val的元素覆盖左边等于val的元素
            if (leftIndex < rightIndex) {
                nums[leftIndex++] = nums[rightIndex--];
            }
        }
        return leftIndex;   // leftIndex一定指向了最终数组末尾的下一个元素
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值