leetcode-88.合并两个有序数组

本文介绍了如何合并两个有序数组的三种方法:1)覆盖0后排序导致时间复杂度和空间复杂度上升;2)创建新数组并排序后拷贝,时间复杂度为O(m+n),空间复杂度为O(m+n);3)逆向双指针原地操作,时间复杂度和空间复杂度均为O(1)。

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


题目

在这里插入图片描述

一、题目分析

该题目的母题是将两个有序递增数组进行合并,要求合并后仍为有序递增数组,且将排好序的数组放入第三个空数组中。本题目与母体解法类似,甚至有更多的解法:

二、解题思路及代码

1.覆盖0后排序

可以将nums2中的内容覆盖nums1数组后面0的位置后进行排序使其有序递增。

int cmp(int* a, int* b) {
    return *a - *b;
}

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    for (int i = 0; i != n; ++i) {
        nums1[m + i] = nums2[i];
    }
    qsort(nums1, nums1Size, sizeof(int), cmp);
}

虽然这种方法直观易解,但这种方法会使得时间复杂度与空间复杂度上升。

时间复杂度:O((m+n)log⁡(m+n))。 排序序列长度为 m+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log⁡(m+n))。

空间复杂度:O(log⁡(m+n))。 排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log⁡(m+n))。

2.创建新数组排序后拷贝

用指针指向一个新数组后用母题的思路将排序好的数字放入新创建的数组,之后拷贝到nums1中即可。
代码如下(示例):

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
       	int* temp=(int*) malloc (sizeof(int)*(m+n));
	int i=0,j=0;
	int k=0;
	while(i<m&&j<n){
	if(nums1[i]<nums2[j])
	  {
		temp[k++]=nums1[i++];
	  } 
	else 
	  {
        temp[k++]=nums2[j++];	 	
      }
  }
    while(i<m){
    	temp[k++]=nums1[i++];
	}
	while(j<n){
		temp[k++]=nums2[j++];
	}
	memcpy(nums1,temp,sizeof(int)*(m+n));  //memcpy(a,b,n):把数组b前n个字符拷贝到a数组中去 
	free(temp);
	temp=NULL;
}

时间复杂度:O(m+n)。 指针移动单调递增,最多移动 m+n 次,因此时间复杂度为 O(m+n)。

空间复杂度:O(m+n)。 需要建立长度为 m+n 的中间数组

3.逆向双指针

nums1的后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进num 的最后面。严格来说,在此遍历过程中的意一个时刻,nums1 数组中有m-p1-1个素被放入 nums1的后半部.nums2数组中有n-p2-1个元素被放入 nums1 的后半部,而在指针p1 的后面,nums1 数组有m+n-p1-1个位置。由于m+n-p1-1>m-p1-1+n-p2-1等价于p2>=1永远成立,因此 p1后面的位置永远足够容纳被插入的元素,不会产生 p1的元素被覆盖的情况。

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
    int p1 = m - 1, p2 = n - 1;
    int tail = m + n - 1;
    int cur;
    while (p1 >= 0 || p2 >= 0) {
        if (p1 == -1) {
            cur = nums2[p2--];
        } else if (p2 == -1) {
            cur = nums1[p1--];
        } else if (nums1[p1] > nums2[p2]) {
            cur = nums1[p1--];
        } else {
            cur = nums2[p2--];
        }
        nums1[tail--] = cur;
    }
}

时间复杂度:O(m+n)。 指针移动单调递减,最多移动 m+n次,因此时间复杂度为 O(m+n)。

空间复杂度:O(1)。 直接对数组 原地修改,不需要额外空间。

以上是解决此问题的三种方法,希望对你有帮助。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值