合并两个有序数组

举报
芒果_Mango 发表于 2022/03/28 10:25:28 2022/03/28
【摘要】 大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流作者简介:CSDN C/C++领域新星创作者https://blog.csdn.net/chuxinchangcun?type=blog掘金LV3用户 https://juejin.cn/us...

大家好,我是芒果,一名非科班的在校大学生。对C/C++、数据结构、Linux及MySql、算法等领域感兴趣,喜欢将所学知识写成博客记录下来。 希望该文章对你有所帮助!如果有错误请大佬们指正!共同学习交流

作者简介:


题目

链接:https://leetcode-cn.com/problems/merge-sorted-array/


题目要求:

image-20220209215642964

注意:

  • 要合并的两个数组都是有序的
  • num1数组的长度为m+n ->即合并在num1数组中
  • 合并后的数组也是非递减的(非降序)

image-20220209215655621


方法1:空间换时间

==思路==:开辟一个m+n大小的数组用来存放合并后的数据

  • 排成非降序的,所以:
  • num1和num2数组的元素进行比较,把小的拷贝到新数组中
  • 因为总有一个数组的元素先拷贝完成,所以要进行判断哪个数组先拷贝结束,然后把另一个数组的元素接着拷贝
  • 把新数组的元素拷贝回去num1数组中,最后释放动态开辟的空间,并且把指针置空

代码

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
	int* arr = (int*)malloc(sizeof(int) * nums1Size);
	if (arr == NULL)
	{
		printf("malloc fail\n");
		return;
	}
	int i = 0;	//控制num1下标
	int j = 0;	//控制num2下标
	int k = 0;//控制arr下标
    
    //i<m && j<n 防止越界
	while (i < m && j < n)
	{
        //num2小,就把num2元素放到arr数组
		if (nums1[i] > nums2[j])
		{
			arr[k] = nums2[j];
			k++;
			j++;
		}
		else
		{
            //num1小,就把num1元素放到arr数组
			arr[k] = nums1[i];
			k++;
			i++;
		}
	}
	//判断谁先结束,下面两个while循环只执行1个
	while (i < m)
	{
		arr[k] = nums1[i];
		k++;
		i++;
	}

	while (j < n)
	{
		arr[k] = nums2[j];
		k++;
		j++;
	}
    //拷贝回去
	for (i = 0; i < nums1Size; i++)
	{
		nums1[i] = arr[i];
	}
    //最后释放动态开辟的空间,并且把指针置空
    free(arr);
    arr = NULL;
}

方法2:排序

==思路==:把nums2数组的数据拷贝到num1数组后面,然后对nums1数组元素进行排序(排成升序)

image-20220209215703509

代码

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    int end1 = m - 1;// num1前面有内容最后元素的下标
	int end2 = n - 1;//num2最后一个元素的下标
	int end = m + n - 1;//num1最后元素的下标
	int i = 0;
	int j = 0;
	//将num2的内容拷贝到num1的后面
	for (i = 0; i < n; i++)
	{
		nums1[end] = nums2[i];
		end--;
	}
	//排序
	for (i = 0; i < m + n-1; i++)
	{
		for (j = 0; j < m + n -1- i; j++)
		{
			if (nums1[j + 1] < nums1[j])
			{
				int  tmp = nums1[j];
				nums1[j] = nums1[j + 1];
				nums1[j + 1] = tmp;
			}
		}
	}
}

方法3:三指针

==思路==:

使用三个下标控制两个数组:

image-20220209215714808


image-20220209215725384

  • end:nums1数组最后一个元素位置下标
  • end1:nums1数组有效数字的最后一个元素位置下标
  • end2:nums2数组最后一个元素下标

  • 从两个数组的最后一个元素比较(因为两个数组都是非递减数组)
  • end1和end2指向的元素进行比较,把大的放在end位置,然后对应end1或者end2下标–,end也要–
  • end1和end2总有一个先不满足条件:(end1>=0 && end2>=0)
    • 如果是nums2数组还未拷贝完成(end2>=0了),就继续拷贝
    • 如果是nums1数组还未拷贝完成, 就不用管了,因为原来的nums1数组是有序的

代码

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    int end1 = m - 1;
	int end2 = n - 1;
	int end = m + n - 1;
	while (end1 >= 0 && end2 >= 0)
	{
		if (nums1[end1] > nums2[end2])
		{
			nums1[end] = nums1[end1];
			end1--;
			end--;
		}
		else
		{
			nums1[end] = nums2[end2];
			end2--;
			end--;
		}
	}
	//有一个先结束
	//当nums1剩余元素没有拷贝时 不用处理,因为nums1数组本身就是有序的
	//当剩余元素没有拷贝的是num2数组:nums2接着拷贝
	while (end2 >= 0)
	{
		nums1[end] = nums2[end2];
		end--;
		end2--;
	}
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。