leetcode 刷题记:88. 合并两个有序数组

很有趣也比较简单的一道题。

问题描述

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

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

1
2
3
4
// @algorithm @lc id=88 lang=javascript 
// @title merge-sorted-array
// @test([1,2,3,0,0,0],3,[2,5,6],3)=[1,2,2,3,5,6]
// @test([1],1,[],0)=[1]

解题思路

方法一 : 合并后排序

这是比较容易想到的解题思路,先把两个数组合并,再排序:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
const merge = function(nums1, m, nums2, n) {
for (let i = 0; i < n; i++) {
nums1[nums1.length - 1 - i] = nums2[i];
}

return [nums1.sort((a, b) => a - b)[0]];
};

方法二 : 双指针 / 从前往后

初始化一个新的数组sorted,用双指针选择最小的值插入到sorted中,最后还要把sorted重新遍历回nums1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
const merge = function(nums1, m, nums2, n) {
let p1 = 0; let p2 = 0;
const sorted = new Array(m + n).fill(0);
let cur;
while (p1 < m || p2 < n) {
if (p1 === m) {
cur = nums2[p2++];
} else if (p2 === n) {
cur = nums1[p1++];
} else if (nums1[p1] < nums2[p2]) {
cur = nums1[p1++];
} else {
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (let i = 0; i != m + n; ++i) {
nums1[i] = sorted[i];
}
};

方法三 : 双指针 / 从后往前

前面两个方法都没有利用到题目中给的一个条件,两个有序数组,另外为了兼容其他语言,数组nums1的长度都足够长了。这次还是用双指针,不过是从数组尾部遍历,找最大的,直接填入到nums1中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
const merge = function(nums1, m, nums2, n) {
let p1 = m - 1; let p2 = n - 1;
let tail = m + n - 1;
let cur;
while (p1 >= 0 || p2 >= 0) {
if (p1 === -1) {
cur = nums2[p2--];
} else if (p2 === -1) {
cur = nums1[p1--];
} else if (nums1[p1] > nums2[p2]) {
cur = nums1[p1--];
} else {
cur = nums2[p2--];
}
nums1[tail--] = cur;
}
};

更 hack 的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
const merge = function(nums1, m, nums2, n) {
let len = m + n;
while (n > 0) {
if (m <= 0) {
nums1[--len] = nums2[--n];
continue;
}
nums1[--len] = nums1[m - 1] >= nums2[n - 1] ? nums1[--m] : nums2[--n];
}
};