题目:给你两个已排序的数组,请帮我合并他们。要求合并之后的数组还是排好序的。
有些同学拿到这道题后,想到的是申明一个新的数组,直接将两个数组合并进来,然后排序,题目中也没有要求复杂度。应该是过关的吧?其实不然,大家细细想下,这样的话我们会浪费一个条件,原来的两个数组已经是排好序的了。显然没有用上。
看过我视频课程的同学可以已经知道了,我们再分而治之,归并排序的时候其实处理过这个问题,今天我们再单独拿出来将一下,让大家更加熟悉数组的操作,下次我们可能要处理的就是合并两个升序链表了。
看图解题:
我们一起看下步骤:
- 检查两个数组,一个数组为空时,返回另一个数组
- 申明一个新的数组,数组大小为两个数组之和
- 三个零时变量:第一个变量控制新的数组,每次有加1,两个数组中只要有一个已经访问结束则终止; 第二个变量控制第一个数组,当该元素小于两个数组,我们就复制到新数组,该变量加一;第三个变量控制第二个数组,当该元素小于第一个数组,我们就复制到新数组,该变量加一
- 我们检查那个数组还有剩余的部分,copy进来
写代码:
在写代码之前,一定要先定义方法签名,这个签名其实就是和别人的契约。一起来看下。
public int[] Merge(int[] a1, int[] a2);
/// <summary>
/// 合并两个数组,将结果放到新的数组里返回
/// </summary>
/// <param name="a1">第一个已经排好序的数组</param>
/// <param name="a2">第二个已经排好序的数组</param>
/// <returns>返回合并好的新数组</returns>
public static int[] Merge(int[] a1, int[] a2)
{
// 当有一个数组为空时,我们返回另外一个数组
if (a1 == null) return a2;
if (a2 == null) return a1;
// 以下代码只会当且仅当两个数组都不为空
int[] result = new int[a1.Length + a2.Length];
int index = 0;
int first = 0;
int second = 0;
// 我们开始扫描数组,当有一个数组全部访问完时,退出while循环
while (first < a1.Length && second < a2.Length)
{
// 比较两个数组的当前值,取小的放到新的数组里
// 之后该数组,和新数组都往后移动一位
if (a1[first] < a2[second])
{
result[index++] = a1[first++];
}
else
{
result[index++] = a2[second++];
}
}
if (first < a1.Length)//说明a1数组有剩余, copy剩余部分
{
while (first < a1.Length)
{
result[index++] = a1[first++];
}
}
if (second < a2.Length) //说明数组a2有剩余,copy剩余部分
{
while (second < a2.Length)
{
result[index++] = a2[second++];
}
}
return result;
}
测试结果我们就不放了哈。下次我们讨论链表的合并问题。思路是一样的。
欢迎大家关注我的公众号,还有我的系列视频教程, 数据结构与算法 和 微软经典算法面试题辅导。大家有什么更好的解法,也欢迎讨论哈。,了解更多基础的数据结构。关注我的公众号,获取最新的算法推送。