leetcode-master/problems/0027.移除元素.md

5.0 KiB
Raw Blame History

笔者在BAT从事技术研发多年利用工作之余重刷leetcode更多原创文章请关注公众号「代码随想录」。

题目地址

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

思路

有的同学可能说了,多余的元素,删掉不就得了。

要清楚数组的元素在内存地址中是连续的,数组中的元素是不能删掉的,只能覆盖。

暴力解法

这个题目暴力的解法就是两层for循环一个for循环遍历数组元素 第二个for循环更新数组。

如动画所示:

很明显暴力解法的时间复杂度是O(n^2)这道题目暴力解法在leetcode上是可以过的。

代码如下:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下表i以后的数值都向前移动了一位所以i也向前移动一位
                size--;// 此时数组的大小-1
            }
        }
        return size;

    }
};

双指针法

双指针法(快慢指针法): 说白了就是通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

先看一下动画理解一下:

代码如下:

// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0; // index为 慢指针
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {  // i 为快指针
            if (val != nums[fastIndex]) { //将快指针对应的数值赋值给慢指针对应的数值
                nums[slowIndex++] = nums[fastIndex]; 注意这里是slowIndex++ 而不是slowIndex--
            }
        }
        return slowIndex;
    }
};

其实双指针法快慢指针法在在数组和链表的操作中是非常常见的很多考察数组和链表操作的面试题都使用双指针法可以将时间复杂度O(n^2)的解法优化为 O(n)的解法,例如:

还有链表找环,也用到双指针:

大家都可以去做一做,感受一下双指针法的内在逻辑!

本题C++代码

暴力解法

时间复杂度O(n^2) 空间复杂度O(1)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
                for (int j = i + 1; j < size; j++) {
                    nums[j - 1] = nums[j];
                }
                i--; // 因为下表i以后的数值都向前移动了一位所以i也向前移动一位
                size--;// 此时数组的大小-1
            }
        }
        return size;

    }
};

双指针解法

时间复杂度O(n) 空间复杂度O(1)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0; // index为 慢指针
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {  // i 为快指针
            if (val != nums[fastIndex]) { //将快指针对应的数值赋值给慢指针对应的数值
                nums[slowIndex++] = nums[fastIndex]; 注意这里是slowIndex++ 而不是slowIndex--
            }
        }
        return slowIndex;
    }
};

更过算法干货文章持续更新可以微信搜索「代码随想录」第一时间围观关注后回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等就可以获得我多年整理的学习资料。