题目如下
思路
首先,我们要明确题目的要求
题目要求我们删除指定元素,并返回移除后数组的长度
那么因此有种想法
一,将指定元素进行覆盖,真正实现删除
二,将非指定元素放置数组的前面部分,并返回个数
PS:第二种解法不满足题目,不使用额外空间的要求,仅作为解决类似题目的思路和讨论时间复杂度和空间复杂度的一种解法
第一种解法:暴力遍历
遍历nums的所有元素,如果等于val,则将后面的所有元素前移覆盖,若不等于,则跳到下一个元素
此时时间复杂度为O(N^2),空间复杂度为O(1)
代码如下:
int time=0;//记录去除后数组长度
for(int i=0;i<numsSize;i++)
{
//若为目标元素,则从此下标从前往后覆盖
if(nums[i]==val)
{
for(int j=i;j<numsSize-1;j++)
{
nums[j]=nums[j+1];
}
}
else
{
time++;//若没有发生覆盖,则为非目标元素,time++
}
}
return time;
第二种解法:新数组法
再次声明,本方法不满足此题目,仅作为类似题目的思路
思路:创建一个新数组arr,同时遍历nums,若不等于val,则放入新数组arr中,并建立变量记录个数。遍历结束后,再拷贝回原先的数组nums,因为题目用指针传nums,说明检查的数组是nums,所以要进行拷贝
这种解法,时间复杂度为O(N),空间复杂度为O(N)
属于牺牲空间换取时间的做法
代码如下
//新创建的数组
int arr[100000]={0};
int time=0;//记录非目标元素个数
//遍历
for(int i=0;i<numsSize;i++)
{
//若果不是目标元素,则放入arr数组
if(nums[i]!=val)
{
arr[time]=nums[i];
time++;//个数+1
}
}
//拷贝到原先的nums数组
for(int i=0;i<time;i++)
{
nums[i]=arr[i];
}
return time;
第三种解法:双指针
第一次接触这种思想,本次博客也主要记录这种方法
PS:事后又了解一些双指针,感觉这种算法很好用很重要
图解如下
第一次画图,大家别介意太丑,能帮助大家理解就好
时间复杂度为O(N),空间复杂度为O(1),效率非常大高的一种解法
那么,具体代码实现如下
//双指针
int right=0;
int left=0;
while(right<numsSize)
{
if(nums[right]!=val)
{
nums[left]=nums[right];
left++;
right++;
}
else
{
right++;
}
}
return left;
总结
虽然这题比较简答,但对于我这样的小白,这三种解法依然给我一些思考和启发
在写oj题时,如果没有题目的限制,我们其实可以先进行最简单的暴力解法,即使这样效率不高,时间复杂度高,但也是一种题解,我们不应该看不起暴力解法,而是要在此基础上,再去寻求更高级的算法,更低的时间复杂度,这是一个思考的过程,一个进步的过程,俗话说,人不能一口吃成一个大胖子,凡是都是积累,沉淀的过程
仅以此激励现在的自己和刚入门有些焦虑的同学们,大家一起加油,一步一个脚印。
感谢大家阅读,阿里嘎多
文章如果有不对或者不足的地方,欢迎大佬们指正,补充。感谢大家的阅读,如果感觉博主写的还可以,麻烦点个赞支持一下,阿里嘎多。拜托了,这对我真的很重要~