20210405 LeetCode 每日一题(合并两个有序数组)

130 阅读1分钟

题目描述

原题链接:合并两个有序数组

给你两个有序整数数组  nums1 和 nums2,请你将 nums2 合并到  nums1  中,使 nums1 成为一个有序数组。

初始化  nums1 和 nums2 的元素数量分别为  m 和 n 。你可以假设  nums1 的空间大小等于  m + n,这样它就有足够的空间保存来自 nums2 的元素。

要求对 nums1 原地操作,不用返回新数组。

示例

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]

解答

解法一

将两个数组拼接到一起再排序。

需要说明的是,输入的 nums1 的长度为 m + n,前 m 个成员是 nums1 实际成员,后面 n 个全是 0,因为在其他语言中一个 list 声明时就已指定长度,而 JavaScript 中的数组不是严格意义上的数组。

代码如下:

var merge = function (nums1, m, nums2, n) {
  nums1.splice(m, nums1.length - m, ...nums2)
  nums1.sort((a, b) => a - b)
}

复杂度分析

  • 时间复杂度:O((M + N) * log(M + N)),拼接需要花费时间 O(M + N),排序按快排时间复杂度 O(log(M + N))。
  • 空间复杂度:O(M + N),按快排复杂度为 O(log(M + N))

解法二

采用逆向双指针,每次比较两个数组最后的成员并在 nums1 数组最后填充进去:

var merge = function (nums1, m, nums2, n) {
  let index1 = m - 1
  let index2 = n - 1
  while (index1 >= 0 || index2 >= 0) {
    const tail = index1 + index2 + 1
    if (index1 === -1) {
      nums1[tail] = nums2[index2--]
    } else if (index2 === -1) {
      nums1[tail] = nums1[index1--]
    } else if (nums1[index1] > nums2[index2]) {
      nums1[tail] = nums1[index1--]
    } else {
      nums1[tail] = nums2[index2--]
    }
  }
}

复杂度分析:

  • 时间复杂度:O(M + N),遍历两个数组总时间复杂度是 O(M + N)
  • 空间复杂度:O(1),原地操作,不占空间