给你两个有序整数数组 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]
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[i] <= 109
(二路归并) O ( n ) O(n) O(n)
ans
用来存贮合并后的有序元素i
,和j
分别指向nums1
和nums2
,每次将两个指针所指向的较小的数添加到ans
中ans
数组赋值给num1
时间复杂度: O ( n ) O(n) O(n)
空间复杂度为: 由于新开了一个数组ans
,因此空间复杂度为 O ( n ) O(n) O(n)。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
vector<int> ans(n+m);
int i = 0, j = 0 , t = 0;
while( i < m && j < n)
{
if(nums1[i] <= nums2[j]) ans[t++] = nums1[i++];
else ans[t++] = nums2[j++];
}
while( i < m) ans[t++] = nums1[i++];
while( j < n) ans[t++] = nums2[j++];
nums1 = ans;
}
};
在上面二路归并算法中,需要临时一个构建一个数组,空间复杂度不是常数,通过观察题,没有充分利用题目所给的条件,nums1
已经开够了足够大,如果直接在nums1
上合并,便不需要额外的空间,而如果从前往后合并,则会覆盖元素得到错误结果,再通过观察,如果从后往前合并的方式,则不会覆盖,是理想的解法,时间 O ( n ) O(n) O(n),空间常数。
步骤如下
k = m + n - 1
i
,和j
分别指向nums1
和nums2
,每次将两个指针所指向的较大的数放在k
的位置,同时i
或者j
和 k
同时减1
while(j >= 0)
再将nums2
中剩余的数放入nums1
中class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int k = m + n - 1;
int i = m - 1,j = n - 1;
while(i >= 0 && j >= 0)
{
if(nums1[i] >= nums2[j]) nums1[k --] = nums1[i --];
else nums1[k --] = nums2[j --];
}
while(j >= 0) nums1[k --] = nums2[j --];
}
};
原题链接:88. 合并两个有序数组