题目描述:
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2
, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,3,0,4] 解释:函数应该返回新的长度5
, 并且 nums 中的前五个元素为0
,1
,3
,0
,4
。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
首先这道题有三种思路,第一种就是暴力求解,两个for循环找到答案,但是当数据过大的时候肯定会TLE;
(个人建议使用)第二种就是用双指针的快慢指针,我们不妨逆思维想一下问题,去除目标元素是不是和保留剩余元素是一样的,所以我们可以用快指针fast去遍历数组,用满指针slow去收集剩余元素
int slow=0;
for(int fast=0;fast<nums.size();fast++){
if(nums[fast]!=val){//只要不是目标元素就是剩余元素
nums[slow++]=nums[fast];
}
}
return slow;
第三种就是相向指针,意思就是两个指针分布在数组的一头一尾,向中间遍历数组(个人不建议使用)
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while (leftIndex <= rightIndex) {
// 找左边等于val的元素
while (leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
// 找右边不等于val的元素
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
-- rightIndex;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素