1、给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例:
输入: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 中的元素。
这个题一个是可以先合并两个数组然后快速排序,这个是最方便的写法。还可以用双指针的方法。
(1)合并+快排
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for (int i =0;i<n;i++){
nums1[m+i]=nums2[i]; //合并
}
sort (nums1.begin(),nums1.end()); //快排
}
};
虽然快排+合并的代码很好写,但是时间复杂度和空间复杂度上较大。时间复杂度为O((m+n)log(m+n));空间复杂度为(log(m+n))。
(2)双指针
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1=0,p2=0;
int nums[m+n];
int pin = 0;
while(p1<m||p2<n){ //保证不会超出界限
if(p1==m){ //nums1遍历完了就继续加入nums2的元素
pin = nums2[p2++];
}else if (p2==n){ //nums2遍历完了就继续加入nums1的元素
pin = nums2[p1++];
}else if (nums1[p1]<nums2[p2]){ //下一个条件同理,加入小数
pin = nums1[p1++];
}else{
pin = nums2[p2++];
}
nums [p1+p2-1]=pin; //把pin里面取到的数加入nums数组
}
for(int a = 0;a<p1+p2;a++){
nums1[a]=nums[a]; //因为题目要求元素在nums1里面,所以要把nums里的元素替换进去。
}
}
};
(3)逆双指针
在(2)中,同样使用的双指针法,但不同的是(3)是从末尾开始遍历,即最大值开始填充进入nums1数组,这样可以避免nums1正向遍历元素被覆盖的问题。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1 = m-1; //双指针,从末尾开始遍历
int p2 = n-1;
int j = nums1.size()-1;
while(p1 >= 0 || p2 >=0){ //防止溢出
if(p1==-1){
nums1[j--] = nums2[p2--];
}else if (p2==-1) {
nums1[j--] = nums1[p1--];
}else if(nums1[p1]<nums2[p2]){
nums1[j--] = nums2[p2--];
}else {
nums1[j--] = nums1[p1--];
}
}
}
};
害,我果然还是太菜了,要多练练啊。