03-移除元素
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
方法一
function removeElement(nums: number[], val: number): number {
let k = 0; // 用于记录不等于 val 的元素数量
for (let i = 0; i < nums.length; i++) {
if (nums[i]!== val) {
// 如果当前元素不等于 val,则将其放到数组的前 k 个位置
nums[k] = nums[i];
k++;
}
}
return k;
}
// 示例调用
const nums = [3, 2, 2, 3];
const val = 3;
const result = removeElement(nums, val);
console.log("剩余元素数量:", result);
console.log("修改后的数组:", nums.slice(0, result));
代码解释
-
初始化计数器:
let k = 0;
:用于记录数组中不等于val
的元素数量。
-
遍历数组:
- 使用
for
循环遍历数组nums
。 - 对于每个元素
nums[i]
,检查其是否不等于val
。 - 如果
nums[i]
不等于val
,将其赋值给nums[k]
,并将k
加 1。这意味着将不等于val
的元素依次放到数组的前k
个位置。
- 使用
-
返回结果:
- 遍历结束后,
k
即为数组中不等于val
的元素数量,将其返回。
- 遍历结束后,
复杂度分析
- 时间复杂度:,其中 是数组
nums
的长度。因为只需要遍历数组一次。 - 空间复杂度:,只使用了常数级的额外空间。
注意事项
- 函数返回的是不等于
val
的元素数量k
,而修改后的数组nums
的前k
个元素包含了所有不等于val
的元素。 - 数组
nums
的其余元素和数组的大小并不重要,因此可以忽略。
方法二
function removeElement(nums: number[], val: number): number {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === val) {
// 使用 splice 方法移除当前等于 val 的元素
nums.splice(i, 1);
// 由于移除元素后数组长度减 1,后续元素会前移,所以需要将索引 i 减 1
i--;
}
}
return nums.length;
}
// 示例调用
const nums = [3, 2, 2, 3];
const val = 3;
const result = removeElement(nums, val);
console.log("移除元素后的数组:", nums);
console.log("剩余元素的数量:", result);
代码解释
- 遍历数组:使用
for
循环遍历数组nums
中的每个元素。 - 检查元素是否等于
val
:对于每个元素nums[i]
,检查它是否等于val
。 - 移除元素:如果
nums[i]
等于val
,则使用splice
方法将该元素从数组中移除。splice
方法的第一个参数是要移除元素的起始索引,第二个参数是要移除的元素个数。 - 调整索引:由于使用
splice
方法移除元素后,数组的长度会减 1,后续元素会向前移动填补空缺,所以需要将当前索引i
减 1,以确保不会跳过下一个元素。 - 返回剩余元素的数量:遍历结束后,返回数组
nums
的长度,即剩余元素的数量。
复杂度分析
- 时间复杂度:,因为在最坏情况下,每次调用
splice
方法都需要将后面的元素向前移动,导致时间复杂度较高。 - 空间复杂度:,只使用了常数级的额外空间。
需要注意的是,虽然 splice
方法可以实现移除元素的功能,但由于其时间复杂度较高,在处理大规模数组时可能性能不佳。相比之下,使用双指针法(如前面提到的方法)的时间复杂度为 ,性能更好。