题目描述:
给你一个数组 nums 和一个值val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例1:
给定 nums=[3,2,2,3],val=3,函数应该返回新的长度2,并且 nums中的前两个元素均为2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums=[0,1,2,2,3,0,4,2],val=2,函数应该返回新的长度5。
并且 nums中的前五个元素为0,1,3,0,4。
你不需要考虑数组中超出新长度后面的元素。
思路:
采用双指针 j和 k,j从头遍历数组,找到 为val值 的位置,然后用k逆序遍历找到 不为val值 的位置,将k位置的值赋给j位置,每次遍历到val值时数组长度减一,当j和k相遇时循环停止,故循环次数为数组长度n次,即时间复杂度为O(n),因为除数组和指针外未申请多余空间故空间复杂度为O(1)。
代码实现:
#include <stdio.h>
#include<ctype.h>
//day-20-29题:原地移除所有数值等于val的元素
typedef int ElemType;
int Dele_val(ElemType *A,int n,ElemType val)//删除函数
{
int j=0,k=n-1,count=n;
//j遍历数组找val,k逆序记录值非val的位置,count记录数组长度
for(j=0;j<n;j++)
{
if(A[j]==val){
count--;//j遍历到val则数组长度减一(计数器)
while(A[k]==val && k>j){
k--;//k逆序找到非val的位置
count--;}
if(j==k) break;//当两指针遇到直接结束循环
A[j]=A[k--];//将k位置的非val值赋给j位置
}
if(j==k) break;//当两指针遇到直接结束循环
}
return count;
}
int main()
{
ElemType nums[1000];
char c;
int i=0;
int n=0;
while((c=getchar()) != '\n')
{
if(isdigit(c))//将输入值转化为字符
{
ungetc(c,stdin);//将c送回输入流
scanf("%d",&nums[n++]);
}
}
ElemType val;
scanf("%d",&val);//读取val值
int length = Dele_val(nums,n,val);//原地删除数组中的val值
printf("%d\n",length);//打印出新长度
return 0;
}