给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
## 示例
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
##解答方法一:直接合并后排序
1
2
3
4
5
6
7
8
9
10
11/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
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))。
排序序列长度为 m+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n))。空间复杂度:O(log(m+n))。
排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。方法二:双指针
利用数组 nums 1与nums 2 已经被排序的性质,将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
var merge = function(nums1, m, nums2, n) {
let newArr=[];
let p1=0,p2=0;
for(i=0;i<m+n;i++){
if(p2 == n){//nums2结束,把nums1后面的直接链接到数组后面
newArr = newArr.concat(nums1.slice(p1,m));
break;
}else if(p1 == m){//nums1结束,把nums2后面的直接链接到数组后面
newArr = newArr.concat(nums2.slice(p2,n));
break;
}else{
newArr[i] = nums1[p1]<=nums2[p2]?nums1[p1++]:nums2[p2++];
}
}
nums1 = newArr;
};复杂度分析
时间复杂度:O(m+n)。
指针移动单调递增,最多移动m+n 次,因此时间复杂度为 O(m+n)空间复杂度:O(m+n)。
需要建立长度为 m+n 的中间数组 sorted。方法三:逆向双指针
由于已知nums1数组的长度是等于合并后的长度,后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进nums 1的最后面。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
var merge = function(nums1, m, nums2, n) {
let newArr=[];
let p1=m-1,p2=n-1;
for(i=m+n-1;i>=0;i--){
if(p2 == -1){//nums2排序结束可以直接退出
break;
}else if(p1 == -1){//nums1排序结束后,继续从nums2中取值
nums1[i] = nums2[p2--]
}else{
nums1[i] = nums1[p1]<= nums2[p2]? nums2[p2--]:nums1[p1--];
}
}
};复杂度分析
时间复杂度:O(m+n)。
指针移动单调递减,最多移动 m+n 次,因此时间复杂度为 O(m+n)。空间复杂度:O(1)O(1)。
直接对数组nums 1原地修改,不需要额外空间。