1. 题目
题目描述
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 (O(1)) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例
输入:nums = 3,2,2,3, val = 3
输出:2, nums = 2,2,*,*
输入:nums = 0,1,2,2,3,0,4,2, val = 2
输出:5, nums = 0,1,4,0,3,*,*,_
约束
-
(0 <= nums.length <= 100)
-
(0 <= numsi <= 50)
-
(0 <= val <= 100)
2. 最佳解题思路描述(快慢双指针,本题标准最优)
-
定义快慢指针:
-
fast快指针:遍历整个数组,逐个检查当前元素; -
slow慢指针:指向有效数组待填充位置,记录不等于 val 的元素存放下标;
-
-
遍历逻辑:
-
若
nums[fast] != val:说明是保留元素,把值赋给nums[slow],慢指针后移; -
若等于 val:直接跳过,慢指针不动;
-
-
遍历结束后,
slow的数值就是新数组长度,直接返回。
优势
-
时间复杂度 (O(n)):仅一次遍历数组;
-
空间复杂度 (O(1)):仅两个临时变量,原地修改,无额外容器;
-
代码极简、逻辑清晰,是数组原地去重 / 移除指定值通用模板。
3. 我的可优化代码(当前代码无逻辑错误,是标准最优解,仅补充优化小细节)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++) {
if (val != nums[fast]) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};
代码说明
-
正确性:代码逻辑完全正确,能通过全部测试用例,属于本题最优写法,无逻辑 bug;
-
可优化小细节(不影响 AC,仅优化拷贝操作):
当前写法存在不必要赋值:当
slow == fast时(前面没有待删除元素),nums[slow] = nums[fast]是自身赋值,可加判断跳过:if (val != nums[fast]) { if(slow != fast) nums[slow] = nums[fast]; slow++; }数组全为保留元素时减少重复赋值,性能微提升。
4. 最优标准代码(你原版,行业通用最简版)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for (int fast = 0; fast < nums.size(); ++fast) {
if (nums[fast] != val) {
nums[slow++] = nums[fast];
}
}
return slow;
}
};
5. 总结
-
快慢双指针是原地移除元素核心模板,本题代码无错误、效率最优,面试直接写;
-
核心规则:快指针负责检索,慢指针负责维护有效数组;
-
返回值是慢指针最终数值,不需要额外计算长度;
-
题目不要求尾部元素清零,无需额外操作。
6. 相关知识拓展
拓展 1:同类快慢指针数组题型模板
-
LeetCode 26 删除有序数组重复项、LeetCode 283 移动零,完全复用快慢指针思想:
快指针遍历筛选有效元素,慢指针存放结果。
拓展 2:另一种解法(首尾双指针,适合删除元素很多的场景)
左右指针,左找待删除值、右找保留值,交换后收缩区间,减少数组赋值次数:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0, right = nums.size() - 1;
while(left <= right){
if(nums[left] == val){
swap(nums[left], nums[right]);
right--;
}else{
left++;
}
}
return left;
}
};
特点:会打乱数组原有顺序,题目允许顺序改变时可用。
拓展 3:复杂度对比
-
快慢指针(你的写法):(O(n)) 时间,(O(1)) 空间,保留原数组顺序;
-
首尾交换双指针:(O(n)) 时间,(O(1)) 空间,数组顺序打乱;
-
暴力 erase:嵌套循环 erase,(O(n^2)) 时间,效率极低,不推荐面试。
拓展 4:快慢指针通用记忆口诀
快指针全遍历,慢指针存有效;
不等目标就留存,慢指针自增记长度。