题目描述
给你一个数组nums
,要求你原地删除所有数值等于val
的元素,并返回移除后数组的新长度
将最终结果插入 nums
的前 k
个位置后返回 k
要求空间复杂度为O(1)
元素顺序可以改变。你不需要考虑数组中超出新长度后面的元素
下面是这道题目的链接
示例:
我们假设数组是nums=0,1,1,3,2,1
,需要删除的数值是val=1
那么输出则是3,nums=0,3,2
对上面的输出做一个解释:函数应该返回新的长度3,新nums中的前三个元素是0,3,2。并且,这三个元素可以为任意顺序,而且你不需要考虑数组中超出新长度后面的元素
思路讲解
那么我们该任何实现原地删除数组值呢?
我们的办法是:双下标
这里我从两个角度分别讲解两个思路:
思路一:
- 我们定义两个下标
des
和src
同时指向数组头部 - 利用
src
向后走,遍历数组,判断所指向的元素是否等于val
- 如果
nums[src]!=val
,说明该元素要被保留,那么就将src指向的值赋给des,即nums[des]=nums[src]
,同时des向后走一步 - 如果
nums[src]==val
,说明该元素要被删除,那么这时候des不进行任何操作 - 等到
src
遍历完数组后,des
的值便是数组的新长度
下面是详细的步骤图:
在这里des扮演了两个角色:
- 被保留的元素所要移到的位置的下标
- 数组的新长度
具体代码实现:
int removeElement(int* nums, int numsSize, int val)
{
int des=0;
int src=0;
while(src<numsSize)
{
if(nums[src]!=val)
{
nums[des]=nums[src];
des++;
}
src++;
}
return des;
}
思路二:
- 我们定义两个下标
des
和src
同时指向数组头部 - 利用
src
向后走,遍历数组,判断所指向的元素是否等于val
- 如果
nums[src]==val
,说明该元素要被删除,那么这时候des加1 - 如果
nums[src]!=val
,说明该元素要被保留,那么就将src指向的元素向前移动des个位置,即nums[src-des]=nums[src]
- 等到
src
遍历完数组后,原数组长度-des
的值便是数组的新长度
下面是详细的步骤图:
在这里des扮演了两个角色:
- 被保留的元素所要前移的位数
- 被删除元素的个数
具体代码是实现:
int removeElement(int* nums, int numsSize, int val)
{
int des=0;
int src=0;
while(src<numsSize)
{
if(nums[src]!=val)
{
nums[src-des]=nums[src];
}
else
{
des++;
}
src++;
}
return numsSize-des;
}