小哆啦开始力扣每日一题的第二天
小哆啦最初的做法
小哆啦手里有一个数组 nums,它的任务是把里面所有等于 val 的坏东西清理掉,只留下有用的好东西。于是,小哆啦拿出一个新袋子(一个新数组),专门装那些不等于 val 的好东西。
首先,小哆啦从头到尾检查 nums 的每一个元素:
- 如果发现一个不是
val的好东西,就赶紧放进袋子里。 - 如果是
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)在原地重新排列好东西。
-
小哆啦从头开始检查
nums数组。- 如果发现好东西(不是
val),它直接把好东西放到记号笔k指向的位置,并把记号笔往前移。 - 如果是坏东西(等于
val),它就直接跳过,不动手。
- 如果发现好东西(不是
-
当检查完所有元素后,记号笔
k就停在好东西队伍的末尾。 -
小哆啦告诉你,这些好东西的数量就是
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)(原地修改,无额外空间)
经过一番优化,小哆啦终于找到了更聪明的做法!它不再为好元素寻找额外的袋子,而是直接在原地动手,把好元素重新排列,既省时又省力,空间也不浪费。整个过程只用了一个指针,轻轻松松就把任务完成了!
回头看,之前使用额外数组的做法虽然也能解决问题,但浪费了空间和时间。小哆啦通过聪明的优化,不仅提升了效率,还让代码变得更简洁、明了。它也意识到,原地修改、减少不必要的操作,往往是提高程序性能的关键。
最终,小哆啦用一个简单而高效的方法,不仅完成了任务,还让自己变得更加聪明!通过这次优化,它不仅收获了更好的代码实现,也让它自己成为了一个更优秀的小程序员!✨