题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
链接:https://leetcode-cn.com/problems/remove-element/
分析
首先我们对这道题目进行分析,我们先不考虑题目中的条件限制,我们可以先考虑可以怎么实现将符合条件的元素删除:
①逐一判断,进行覆盖
我们可以通过将顺序表中学习到的内容进行复用,就是说我们对数组中的每一个元素都进行判断,如果我们当前比较的元素与val相同,那么我们就可以执行我们在顺序表中实现的接口——删除指定位置的元素,因为这个接口的实现是将当前位置的下一个位置的数据将当前位置的元素覆盖,直至最后一个元素被覆盖,然后将数组长度减一,就这样我们对数组中的所有元素判断结束时,我们也就实现了题目的要求。
此时我们当前的方法的时间复杂度为:O(N^2);空间复杂度为O(1);
当这样我们的时间复杂度过高,那么我们有什么更好的方法呢?
②双指针
这里我们讲解一种经典的解法——双指针;在这里我们先创造两个指针,共同指向我们数组的首元素,分别为src、dst;我们用src去遍历我们数组中的所有元素,然后每当指向的元素与我们的val相同,那么我们就让scr跳过这个元素,继续指向下一个元素;如果我们当前指向的元素与我们的val不同,那么我们将当前的元素内容覆盖到我们dst当前指向的数组位置,然后src和dst继续指向下一个元素,这样当我们的src指针指向的位置超出我们的数组长度时,我们也就将数组遍历结束,这个时候我们就实现了我们的目标;
此时我们的时间复杂度为:O(N);空间复杂度为:O(N);
图解
代码
int removeElement(int* nums, int numsSize, int val){
int src = 0,dst = 0;
while(src<numsSize)
{
if(nums[src] == val)
{
src++;
}
else
{
nums[dst] = nums[src];
src++;
dst++;
}
}
return dst;
}
总结
在这道题目中我们学到了可以使用双指针来解决问题,一个用判断,一个用来实现新的数组,这种思想在顺序表和链表中经常使用。
以上就是我对这种方法的个人理解
上述内容如果有错误的地方,还麻烦各位大佬指教【膜拜各位了】【膜拜各位了】