思路
既然不能使用额外的空间,那就不能重新创建一个数组。
题目说元素的顺序可以改变,因此可以换一个思路:不去真正的删除元素,而是给这个位置换一个值。既然最后返回的是新数组的长度,那么尾部的元素就是被抛弃的元素,因此可以把要删除的元素和尾部的元素交换。
代码
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int j = nums.size() - 1; // j指向末位元素
// 用i从首位元素开始遍历,左右同时向中间逼近
for (int i = 0; i <= j; i++) {
// 用j从末位元素开始删除直到达到一个非val值
while (nums[j] == val) {
j--;
}
// 如果nums[i]等于val,则把最右侧的非val值赋给它,并递减j
if (nums[i] == val) {
nums[i] = nums[j--];
}
}
return j + 1;
}
};
这样的代码在遇到数组为[1],val为1时就会出错。在while里j已经减到了-1,在后面的if里还继续访问nums[j]就会引发错误。
在while循环里加入判断遍历结束的条件即可:
while (nums[j] == val) {
j--;
// 如果已经结束遍历了就返回
if (j < i)
return j + 1;
}
总结
整个数组最多遍历一次,时间复杂度为 O ( n ) O(n) O(n)。