题目:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素.
class Solution {
/*
这是二刷啦~~~
下面两种写法,其实都是双指针法:
对于第一种写法,是以 fast 为循环,通过覆盖处理,
用 for 循环 ,不相等的时候就做赋值,将原本的覆盖掉,如果相等就直接下一轮循环
对于第二种写法,是通过与最后一个元素进行交换的思想
也是两个指针,初始时,一个指向首,一个指向尾
当首部出现 val 就与尾指针元素做交换,同时right--,注意此时 left 不做任何操作,
而当没有出现 val时,就left++
*/
public:
// int removeElement(vector<int>& nums, int val) {
// int slow = 0;
// for(int fast = 0; fast < nums.size(); ++fast)
// {
// // 这里对于 if 的处理,着实没想到呢~
// if(nums[fast] != val)
// {
// // 这里没有做交换,是覆盖了前面的值
// nums[slow] = nums[fast];
// ++slow;
// }
// }
// return slow;
// }
int removeElement(vector<int>& nums, int val)
{
int left = 0, right = nums.size();
while(left != right)
{
if(nums[left] == val)
{
// 注意这里数组不要越界了 是 nums[right - 1]
swap(nums[left], nums[right - 1]);
right--;
}
else
{
left++;
}
}
return right;
}
};
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
// //第一种暴力解法,时间复杂度为O(n^2),空间复杂度为O(1)
// int n=nums.size();
// //这里的终止条件我写错了,写成了i<n-1
// for (int i = 0; i < n; i++)
// {
// if (val == nums[i])
// {
// for (int j = i; j < n - 1; j++)
// {
// nums[j] = nums[j + 1];
// }
// i--;
// n--;
// }
// //因为所有的数值都向前移动了一位,所以i和n也需要减1
// }
// return n;
// //第二种双指针法:通过一个快指针和一个慢指针,在一个for循环下完成两个for循环的工作
// int slowIndex=0;
// for(int fastIndex=0;fastIndex<nums.size();++fastIndex)
// {
// // if(nums[fastIndex]==val)
// // {
// // continue;
// // }
// // else
// // {
// // nums[slowIndex]=nums[fastIndex];
// // ++slowIndex;
// // }
// //注释部分可以写为更加简洁的代码
// if(nums[fastIndex]!=val)
// {
// nums[slowIndex]=nums[fastIndex];
// ++slowIndex;
// }
// }
// return slowIndex;
//第三种 因为题中说了可以改变元素顺序,因为可以与最后一个元素换位置
int n=nums.size(),i=0;
while(i!=n)
{
if(val==nums[i])
{
swap(nums[n-1],nums[i]);
n--;
}
else
{
i++;
}
}
return n;
}
};