给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
思路1:把两个数组合并到一起,然后调用sort函数直接排序。代码简单,但是时间复杂度较高。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for(int i=0,j=m;j<n+m;++i,++j){
nums1[j]=nums2[i];
}
sort(nums1.begin(),nums1.end());
}
};
思路2:容易想到的是比较两个数组,然后把每个较小的存入第三个数组,但这样增加了空间复杂度,违反题意。所以考虑到使用nums1的额外的空间,先把nums1的元素备份到nums1额外的空间去,然后双指针比较再插入即可。
运行不成功。原因是nums1的指针查询完之后,而nums2的指针还没到头,则需要把nums2的元素直接覆盖到nums1后面的位置。现在实现的只是push进了nums1中。还有待改进。
class Solution {
public:
void merge(vector& nums1, int m, vector& nums2, int n) {
//拷贝nums1
for(int i=0,j=m;j<n+m;++i,++j){
nums1[j]=nums1[i];
}
//双指针比较 较小的放在nums1的考前部分
int cnt=0.,cnt1=0;
for(int i=0,j=m;j<n+m; ){
if(nums1[j]<=nums2[i]){
nums1[cnt++]=nums1[j];
++j;
}
else{
nums1[cnt++]=nums2[i];
++i;
++cnt1;
}
}
for(cnt1;cnt1<n;++cnt1){
nums1[cnt++]=nums2[cnt1];
}
}
};
思路三:看了题解的思路从后向前比较后较大的插入,思路比较简单,自己写代码后报错溢出,不知道为什么。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
//使用nums1的额外空间 从后向前使用双指针法 把较大的放在靠后的位置
int k=n+m-1;
for(int i=m-1;i>=0; ){
for(int j=n-1;j>=0; ){
if(nums1[i]>nums2[j]){
nums1[k--]=nums1[i];
--i;
break;
}
else{
nums1[k--]=nums2[j];
--j;
}
}
}
}
};
题解代码很优秀,尤其是if判断条件写的相当好,当减到小于0以后,就持续从下标i写入。如果是nums1先减到0而nums2还没减到0时,则持续用nums2向nums1写入。思路太棒了,我就是因为没有考虑出该如何解决当一个数组减至0的情况。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for(int i=m-1,j=n-1,k=n+m-1;k>=0;--k){
if(j<0||i>=0&&nums1[i]>nums2[j]){
nums1[k]=nums1[i--];
}
else{
nums1[k]=nums2[j--];
}
}
}
};