小哆啦移除元素

109 阅读4分钟

小哆啦开始力扣每日一题的第二天

题目链接27. 移除元素 - 力扣(LeetCode)

小哆啦最初的做法

小哆啦手里有一个数组 nums,它的任务是把里面所有等于 val 的坏东西清理掉,只留下有用的好东西。于是,小哆啦拿出一个新袋子(一个新数组),专门装那些不等于 val 的好东西。

首先,小哆啦从头到尾检查 nums 的每一个元素:

  1. 如果发现一个不是 val 的好东西,就赶紧放进袋子里。
  2. 如果是 val,那就是坏东西,小哆啦直接跳过。

检查完后,小哆啦拿着满满的袋子回到 nums 家里,把袋子里的好东西一件一件摆回去,让它们重新整整齐齐地站好队。最后,小哆啦开心地告诉你袋子里有多少好东西,这个数字就是新数组的长度啦!✨ 小哆啦觉得带着一个袋子跑来跑去虽然能完成任务,但效率不够高。于是它决定聪明点,直接用自己的工具箱(也就是数组 nums 本身)来处理这些元素。它用一个记号笔(一个指针 k)在数组上标记出好东西的位置,边检查边把好东西搬到前面去,再也不用额外的袋子了!

小哆啦最初代码实现

function removeElement(nums: number[], val: number): number {
    // 小哆啦的袋子,用来装好东西
    let arr: number[] = [];

    // 步骤1:检查每一个元素,把好东西放进袋子
    for (let index = 0; index < nums.length; index++) {
        if (nums[index] !== val) {
            arr.push(nums[index]); // 好东西装进袋子
        }
    }

    // 步骤2:把袋子里的好东西重新摆回 nums
    for (let index = 0; index < arr.length; index++) {
        nums[index] = arr[index];
    }

    // 步骤3:告诉袋子里有多少好东西
    return arr.length;
}

  • 时间复杂度:O(n)

  • 空间复杂度:O(n)(由于使用了额外的数组 arr


小哆啦的优化步骤

小哆啦想了一下,发现自己以前做事虽然能完成任务,但有点浪费时间和空间。于是,它决定用一种更聪明的方式来优化任务,让效率更高,空间更省。这里的关键思路是:不再用额外的袋子,而是通过指针(记号笔 k)在原地重新排列好东西。

  1. 小哆啦从头开始检查 nums 数组。

    • 如果发现好东西(不是 val),它直接把好东西放到记号笔 k 指向的位置,并把记号笔往前移。
    • 如果是坏东西(等于 val),它就直接跳过,不动手。
  2. 当检查完所有元素后,记号笔 k 就停在好东西队伍的末尾。

  3. 小哆啦告诉你,这些好东西的数量就是 k,数组前面那一部分就是整理好的!

function removeElement(nums: number[], val: number): number {
    let k = 0; // 记号笔,指向好东西的位置

    // 小哆啦开始检查每个元素
    for (let index = 0; index < nums.length; index++) {
        if (nums[index] !== val) {
            nums[k] = nums[index]; // 好东西搬到前面
            k++; // 记号笔向前移动
        }
    }

    // 返回好东西的数量
    return k;
}
  • 时间复杂度:O(n)(只遍历一次数组)
  • 空间复杂度:O(1)(原地修改,无额外空间)

经过一番优化,小哆啦终于找到了更聪明的做法!它不再为好元素寻找额外的袋子,而是直接在原地动手,把好元素重新排列,既省时又省力,空间也不浪费。整个过程只用了一个指针,轻轻松松就把任务完成了!

回头看,之前使用额外数组的做法虽然也能解决问题,但浪费了空间和时间。小哆啦通过聪明的优化,不仅提升了效率,还让代码变得更简洁、明了。它也意识到,原地修改、减少不必要的操作,往往是提高程序性能的关键。

最终,小哆啦用一个简单而高效的方法,不仅完成了任务,还让自己变得更加聪明!通过这次优化,它不仅收获了更好的代码实现,也让它自己成为了一个更优秀的小程序员!✨