一句话说透数据结构里面的给定两个有序数组,合并它们并返回一个新的有序数组

155 阅读2分钟

一句话总结:
合并两个有序数组就像把两队按身高排队的小朋友合并成一队——每次从两队最前面挑最矮的放进新队伍,直到所有小朋友排好队!


一、双指针法(最优解)

原理:  用两个指针分别指向两个数组的起始位置,每次取较小的值放入新数组,直到所有元素处理完毕。

fun mergeSortedArrays(arr1: IntArray, arr2: IntArray): IntArray {
    val merged = IntArray(arr1.size + arr2.size) // 创建新数组
    var i = 0 // arr1的指针
    var j = 0 // arr2的指针
    var k = 0 // merged的指针

    // 两队都还有人时,挑更小的放进去
    while (i < arr1.size && j < arr2.size) {
        merged[k++] = if (arr1[i] <= arr2[j]) arr1[i++] else arr2[j++]
    }

    // 处理剩下的arr1元素
    while (i < arr1.size) merged[k++] = arr1[i++]
    
    // 处理剩下的arr2元素
    while (j < arr2.size) merged[k++] = arr2[j++]

    return merged
}

时间复杂度:  O(m + n) (m和n是两个数组的长度)
空间复杂度:  O(m + n) (需要新数组存储结果)


二、测试用例

fun main() {
    // 测试用例1:普通情况
    val arr1 = intArrayOf(1, 3, 5)
    val arr2 = intArrayOf(2, 4, 6)
    println(mergeSortedArrays(arr1, arr2).contentToString()) 
    // 输出 [1, 2, 3, 4, 5, 6]

    // 测试用例2:一个数组为空
    val emptyArr = intArrayOf()
    val arr3 = intArrayOf(2, 4)
    println(mergeSortedArrays(emptyArr, arr3).contentToString())
    // 输出 [2, 4]

    // 测试用例3:有重复元素
    val arr4 = intArrayOf(1, 2, 2)
    val arr5 = intArrayOf(2, 3)
    println(mergeSortedArrays(arr4, arr5).contentToString())
    // 输出 [1, 2, 2, 2, 3]
}

三、分步图解

初始状态:
arr1: [1, 3, 5]  指针i=0
arr2: [2, 4, 6]  指针j=0

第1步:选1(i=0)→ merged: [1]
第2步:选2(j=0)→ merged: [1, 2]
第3步:选3(i=1)→ merged: [1, 2, 3]
第4步:选4(j=1)→ merged: [1, 2, 3, 4]
第5步:选5(i=2)→ merged: [1, 2, 3, 4, 5]
最后把arr2剩下的6加入 → 完成!

四、其他方法对比

方法时间复杂度适用场景
双指针法O(m + n)最优解,推荐使用
合并后排序O((m+n)log(m+n))代码简单但效率低

五、常见问题

Q1:如果输入数组无序怎么办?
A:先排序再合并,但时间复杂度会增加(取决于排序算法)。

Q2:能否原地合并节省空间?
A:如果arr1预先留有足够空间(如LeetCode 88题),可以逆向双指针,但本题要求返回新数组。

口诀:
有序数组合并不难,
双指针法走前端。
你一个来我一个,
谁小谁进新家园!