【手撕OJ题】——88、合并有序数组(两种思路:C实现)

本文介绍了如何合并两个有序数组,提供了两种方法:一种是开辟额外空间的直接合并,另一种是利用双指针从后向前合并。第一种方法虽然简单易懂,但空间复杂度较高;第二种方法巧妙地利用了数组空间,实现了空间复杂度为O(1)的解决方案。两种方法的时间复杂度均为O(n+m),其中n和m分别是两个数组的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:88、合并有序数组


在这里插入图片描述

方法①-开辟额外空间

思路:辟一个新空间nums;从头开始,nums1和nums2比较,小的放到nums中即可,相同的取第一个;
同时要注意:可以有nums1放完和nums2没放完的情况;还有nums2放完,nums1没放完的情况。
最后再把nums的值拷贝回去nums1即可;

时间复杂度O(n+m);
空间复杂度O(n+m);

请添加图片描述

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
	int first = 0; //nums1的下标
	int second = 0; //nums2的下标
	//开辟大小为m+n的数组,为的是能够容纳nums1和nums2的值
	int* nums  = (int*)malloc(sizeof(int)*(m+n));
	int third = 0; //nums的数组下标
	
	while(first < m && second < n) //在不越界的情况下,都继续循环
	{		
		if(nums1[first] < nums2[second])
        {
			nums[third++] = nums1[first++]; //赋值时候不要忘记下标的移动
		}
        else
        {
			nums[third++] = nums2[second++];
		}
	}
	//退出循环后,要考虑nums1和nums2哪个没有赋值完到nums中
	while(first < m) //退出循环后,first < m说明nums1还没有赋值完到nums中
	{
		nums[third++] = nums1[first++];	
	}
	while(second < n)//退出循环后,second < n说明nums1还没有赋值完到nums中
	{
		nums[third++] = nums2[second++];
	}
	
	//最后把nums的值拷贝回去nums1中
	memcpy(nums1,nums,sizeof(int)*(m+n));
	free(nums);
}

在这里插入图片描述

方法②-双指针

思考:从前往后两两对比吗?
不行,因为如果是下图这样的示例,比如1和0比较,小的放到nums1,就会覆盖掉原数据

这里是引用

那交换呢?

在这里插入图片描述
像上面这个案例就不行了

倒着比,可能就是最优解。从后往前合并,由于题目给出nums1的空间是比较大的,我们可以利用这个特性,合并到nums1中,不需要开辟额外的空间。
从nums1和nums2的有效数据后面,哪个大的就放到nums1的最后面;
情况1:nums2先放完
请添加图片描述

情况2:nums1放完了,nums2还没放完,直接把nums2的都赋值过去给nums1即可;

时间复杂度O(n+m);
空间复杂度O(1);

写代码时,nums1Size和nums2Size可以不用动

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    int end1 = m - 1,end2 = n - 1;
    int i = m + n - 1;
    while(end1 >= 0 && end2 >= 0)
    {
        if(nums1[end1] > nums2[end2])
        {
            nums1[i] = nums1[end1];
            i--;
            end1--;
        }
        else
        {
            nums1[i] = nums2[end2];
            i--;
            end2--;
        }
    }

    // end2结束,nums2的数组都拷贝过去了,那么不用处理

    // end1结束,nums1的数组都拷贝过去了,那么需要再把nums2剩下数据拷贝过去
    while(end2 >= 0)
    {
        nums1[i] = nums2[end2];
        i--;
        end2--;
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值