Day20 算法题-第29题:原地移除所有数组中数值等于val的元素

97 阅读2分钟

题目描述:

给你一个数组 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。

你不需要考虑数组中超出新长度后面的元素。

思路:

采用双指针 jk,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;
}

输出结果:

1、常规情况;

123123.png

2、极端情况;

213213.png

3、未有对应值情况:

333222333.png