练习(移除元素+合并两个数组)

一、移除元素

有一个数组 nums 和一个变量 val,你需要原地移除所有数值等于val的元素,并返回移除后数组的新长度,不要使用额外的数组空间

示例:输入:nums={3,2,2,3},val=3        输出:2,nums={2,2}
           输入:nums={0,1,2,2,3,0,4,2},val=2     输出:5,nums={1,3,0,4,2}

思路:使用双指针法(快慢指针)

创建两个变量 src(源数据)和 dst(目标数据),

1)若src指向的值为val,src++,

2)若不是val,nums[dst]=nums[src],src++,dst++

(src是快指针,用来遍历数组,而dst是慢指针,用来存放有效的数组元素)

代码实现:

//方式1
int removeElement(int* nums,int numsSize,int val)
{
    int src = 0;
    int dst = 0;
    while(src < numsSize)
    {
        if(nums[src] == val)
        {
            src++;
        }
        else
        {
            //赋值,两指针++
            nums[dst] = nums[src];
            dst++;
            src++;
        }
    }
    //此时dst的刚好就是新数组的有效长度(有效元素个数)
    return dst;
}
//方式二
int removeElement(int* nums,int numsSize,int val)
{
    
    int src = 0;// src是慢指针,指向下一个有效数字
    int dst = 0;// dst是快指针,遍历数组
    for(src = 0;src < numsSize; src++)
    {
        if(nums[src] != val)// 当前元素不等于val
        {
            nums[dst] = nums[src];// 将有效元素复制到慢指针位置
            dst++;// 慢指针前进
        }
    }
    return dst;// 返回新长度(有效元素个数)
}

int main()
{
    int nums[] = {3,2,2,3};
    int val = 3;
    int numsSize = sizeof(nums)/sizeof(nums[0]);
    printf("原始数组:");
    for(int i = 0;i < numsSize; i++)
    {
        printf("%d ",nums[i]);
    }
    printf("\n");

    int newSize = removeElement(nums,numsSize,val);
    printf("移除%d后数组的新长度为%d\n",val,newSize);
    printf("新数组:");
    for (int i = 0; i < newSize; i++)
	{
		printf("%d ", nums[i]);
	}
	printf("\n");
    return 0;
}

接下来我们顺便实现一下可以额外添加数组的方式:

思路:将移除val后的元素存放在 tmp[] 数组中

首先先创建好 nums数组,数组元素为3,2,2,3;接着创建val变量,即要移除的元素,肯定需要遍历数组,所以需要计算好nums数组的长度,可以先将nums数组,即原始的数组先打印出来与后续进行对比(数组需要遍历打印),

然后我们写一个函数来求移除val后的数组长度,函数的参数有原始数组,数组长度以及val,在函数内部,我们先开辟一个新的数组tmp(使用动态开辟,记得对返回值进行判断),再加一个变量count,记录非val的元素,同时作为tmp数组的下标使用,接下来遍历一下原数组,筛选一下非val的元素(for+if),然后赋值给新的数组tmp,最后将结果重新复制到原始数组中,接着对tmp进行free释放然后置为空指针,返回count(移除后数组的新长度)

int removeElement(int* nums,int numsSize,int val)
{
    //创建临时数组
    int* tmp = (int*)malloc(numsSize*sizeof(int));
    int count = 0;//记录非val的元素
    if(tmp == NULL)
    {
        perror("malloc");
        return 1;
    }
    // 遍历原数组,筛选非 val 元素
    for(int i = 0;i < numsSize; i++)
    {
        if(nums[i] != val)
        {
            tmp[count] = nums[i];// 将有效元素存入临时数组
            count++;
        }
    }
    //将结果复制到原数组
    for(int i = 0;i < count; i++)
    {
        nums[i] = tmp[i];
    }
    //释放
    free(tmp);
    tmp = NULL;
    return count;
}
int main()
{
    int nums[] = {3,2,2,3};
    int val = 3;
    int numsSize = sizeof(nums)/sizeof(nums[0]);
    printf("原始数组:");
    for(int i = 0;i < numsSize; i++)
    {
        printf("%d ",nums[i]);
    }
    printf("\n");
    
    int newSize = removeElement(nums,numsSize,val);
    printf("移除%d后数组的新长度为%d\n",val,newSize);
    printf("新数组:");
    for (int i = 0; i < newSize; i++)
	{
		printf("%d ", nums[i]);
	}
	printf("\n");
    return 0;
}

二、合并两个数组

有两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元数个数,请你合并nums2到nums1中,使合并后的数组同样按非递减顺序排列

示例:

输入:nums1={1,2,3,0,0,0}; m=3,
          nums2={2,5,6};       n=3      

输出:{1,2,2,3,5,6}

思路:我们还是按第一道题的思路进行,使用双指针,从前往后开始遍历,假设nums1数组采用L1变量,nums2数组使用L2变量,接下来拿两个数组中的元素进行比大小,以给出的示例为例,此时nums1[L1]=3 > nums2[L2]=2,那么就要将nums2[L2]这个元素移到nums1[L1]这个位置上,而我们注意到此时nums1[L1]位置原本的元素就被覆盖掉了,所以这样的思路是不对的

那么应该如何做呢?还是用指针的方式,要从后往前开始遍历比大小(比谁大,谁大谁往后放),除此之外还需要增加一个变量L3,用来表示nums1数组中的最后一个元素的位置,而L1,L2两个指针并不是简单的从后面开始,而是数组的第三个元素开始从后往前遍历(以nums2数组元素个数为准,两个数组对齐元素个数,而题目也说了m,n=3分别表示两个数组的元素个数,这就可以直接使用)

具体操作:(1) L2先出循环

(2)L1先出循环,nums2中还有数据未放到nums1中

代码实现:

(需要遍历数组,因此需要求数组长度,但是我们已知m,n,可以用这两个变量来求)

void merge(int* nums1,int m,int* nums2,int n)
{
    int L1 = m-1;
    int L2 = n-1;
    int L3 = m+n-1;
    while(L1>=0 && L2>=0)//只要有一个条件不满足就退出循环
    {
        if(nums1[L1] < nums2[L2])
        {
            nums1[L3--] = nums2[L2--];
        }
        else
        {
            nums1[L3--] = nums1[L1--];
        }
    }
    //除了循环有两种情况:L1>=0或L2>=0,只需要处理L2>=0的情况(说明L2中的数据还没有完全放入到nums1中)
    while(L2 >= 0)
    {
        nums1[L3--] = nums2[L2--];
    }
    //此时nums1中包含了nums2中的数据,nums1是升序数组
}
int main()
{
    int nums1[] = {1,2,3,0,0,0};
    int nums2[] = {2,5,6};
    int m = 3;
    int n = 3;
    merge(nums1,m,nums2,n);
    for(int i = 0;i < m+n; i++)
    {
        printf("%d ",nums1[i]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值