【问题标题】:How do I merge two sorted arrays?如何合并两个排序数组?
【发布时间】:2021-10-11 09:32:15
【问题描述】:

两个长度分别为mn的数组(nums1nums2)必须合并,并在数组nums1中排序。 nums1 的长度是 m+nnums1 中的最后一个 n 元素是 0。 不退货,nums1 必须修改。 LeetCode question

示例

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

我们要合并的数组是[1,2,3][2,5,6]。合并的结果是[1,2,2,3,5,6],下划线的元素来自nums1。

我已经完成了这个问题,但不知道为什么它不起作用。

var merge = function(nums1, m, nums2, n) {
    let j = 0
    for (let i = m; i < n; i++) {
      nums1[i] = nums2[j]
      j++
    } 
};

驱动代码:

let nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
merge(nums1, m, nums2, n)
console.log(nums1)

输出:

[1, 2, 3, 0, 0, 0]

【问题讨论】:

  • 您误解了mn 的用途。您应该在调试器中单步执行此操作,您会很快注意到您的循环从未进入。
  • 请在 leetcode 讨论算法问题。我记得 .net 有 Union 操作左右

标签: arrays sorting merge


【解决方案1】:

使用数组的concat函数,然后排序函数

例如

num1 = num1.concat(num2)
num1.sort()

num1 = num1.concat(num2).sort()

【讨论】:

  • 它在返回 nums1 时起作用,但如果函数只是修改 nums1,则串联似乎不起作用。
  • 这不会修改num1,所以不符合问题大纲。
【解决方案2】:

你在搜索这样的东西吗?

nums1 = [...nums1, ...nums2].sort().filter(i => i != 0);  
console.log(nums1);

这里采取的步骤:

  1. 先接触二阵
  2. 然后对数组进行升序排序
  3. 然后从数组中删除0

看看这个:

tempNums1 = nums1.slice(0, m);
tempNums2 = nums2.slice(0, n);
arr = [...tempNums1, ...tempNums2].sort((a,b) => { return a - b; });
nums1.splice(0, nums1.length);  
for(let i=arr.length - 1;i>=0;i--){
    nums1.unshift(arr[i]);
}

这里的 hack 是 spliceunshift 在函数范围之外生效

更新:

 nums1.splice(m, nums1.length);// O(n)
 for(let j=0; j< n; j++){
     nums1.unshift(nums2[j]); // O(n)
 }
 nums1.sort((a, b) => a - b); // O(n log n)

【讨论】:

  • 这不会修改nums1引用的数组,按照问题要求:不返回,必须修改nums1。
  • 我已经更新了sn-p的代码。现在可以用了吗?
  • 我没试过,但也许吧。它缺少这个 excersize 的很大一部分,它可以在不占用空间的情况下就地操作。 “跟进:你能想出一个运行时间为 O(m + n) 的算法吗?”
  • @Alexander 我已经更新了另一个实现(我认为现在内存消耗较低)。看看这个。目前,我还没有任何想法以 O(m+n) 的时间复杂度来实现它。
  • 我的回答说明了这一点。
【解决方案3】:

您误解了mn 的用途。您应该在调试器中单步执行此操作,您会很快注意到您的循环从未进入。

它们不是“零区域”的第一个和最后一个索引。它们是第一个索引,之后找到的零计数(与将合并到 num1num2 数组一样长。如果名称不像 @ 那样无用,这将更加明显987654325@和n

对此的高效解决方案将涉及就地执行此操作(实际上,问题概述 requires 是您修改 num1 而不是创建新数组)。

您知道两个数组都已排序,因此“合并”只需要您从每个数组中选择最小的元素。问题是您在num10s)中的所有“可用空间”都位于后面,这使得它必须在数组的开头腾出空间来插入来自num2 的元素。

相反,您可以依赖以下事实:从最小到最大排序的数组在反转时也会被排序,除了从最大到最小排序。虽然这可能很明显,但这是关键技巧:您从结尾开始填写num2,并朝着开始努力。在每一步中,您都会替换 0(最终替换其他数字)with the largest element from the "tail" ofnum1ornum2`。

从头到尾执行此操作会给您带来O(n) 的时间复杂度,而不会使用额外的空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 2019-07-21
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    相关资源
    最近更新 更多