题目描述
题目:合并两个有序数组,使其保持不递减的顺序排列。
样例
nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3;
合并后的nums1数组为:[1,2,2,3,5,6]
算法1
(双指针)
题目让从两个不递减数组中挑选元素,使其合并成一个不递减的数组,可以考虑归并排序的模型,使用两个指针i,j分别指向两个数组开头,逐个比较指针所指元素的大小,小的那个挑选出来。新开辟一个数组nums其大小为 m + n m + n m+n用来保存满足条件的元素。最后再将nums数组里的元素拷贝到nums1中。
时间复杂度
O(m+n)
空间复杂度
开辟了一个数组nums用来中转元素,所以空间复杂度是O(m+n)
C++ 代码
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = 0, j = 0;
vector<int>temp(m+n);
while((i < m) && (j < n)){
if(nums1[i] < nums2[j]){
temp.push_back(nums1[i]);
i++;
}
else{
temp.push_back(nums2[j]);
j++;
}
}
while(i < m) temp.push_back(nums1[i]),i++;
while(j < n) temp.push_back(nums2[j]),j++;
// 这里有个坑,由于temp默认初始化为0,所以拷贝时要将前面的元素略过。
for(int i = 0; i < m + n; i++)
nums1[i] = temp[i + m + n];
}
};
算法2
(倒着放)
注意到题目中已经将nums1的大小设置为m+n了,而正着放会覆盖掉nums1中的元素,所以上面的方法额外使用了一个数组存放选中的元素。可以发现:倒着放的情况下,由于nums1后面n个元素都是0,所以不会存在元素被覆盖掉的现象,这样直接在原数组中操作,节省了空间。
时间复杂度
O(m+n)
空间复杂度
O(1)
C++ 代码
先考虑思路再考虑细节。确实是一个好的方法hh
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1;
for(int k = m + n - 1; k >= 0; k--){
if(j < 0 || (i >= 0 && nums1[i] >= nums2[j])) nums1[k] = nums1[i--];
else nums1[k] = nums2[j--];
}
}
};