合并两个有序数组(c++)

题目

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

解题思路如下:(向后看,因为通过观察可知nums1数组向后为空,故可覆盖使用。)

1.使用swap()函数

已知nums1数组长度为m+n,nums1的元素个数为m,nums2的元素个数为n。

vector使用size()得到数组长度。

代码如下:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int length=nums1.size();
        length--;//全部减一为地址
        m--;
        n--;
        while(n>=0)
        {
            while(m>=0&& nums1[m]>nums2[n])//m一定要大于0,因为当num1=[0]的时候m=-1,如果不大于等于0则会运行该条语句出现错误。
            {swap(nums1[m--],nums1[length--]);
            }
        
            swap(nums1[length--],nums2[n--]);
         }
    
        return ;
}
};

使用swap函数的方法也可以用赋值表示,但是赋值的话使用的时间更久,对于内存占用较为不优化,个人较推荐swap()函数方法。

2.使用a?b:c函数

时间复杂度相较于第一种方法较低,注意使用insert和erase函数的时候注意区间为左闭右开。

[0,0)则无法选0。故需要在length+1因为无法选取到1,可以尝试不+1看运行结果会报什么错误,一开始忘记左闭右开区间一直报错TvT。

使用erase()函数是因为,比如会有情况如下:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int length=nums1.size();
         length--;
         n--;
         m--;
         while(n>=0 && m>=0)
         { 
           nums1[length--]=nums1[m]>nums2[n]?nums1[m--]:nums2[n--];
         }
         if(n>=0 && m<0)
         {
             nums1.erase(nums1.begin(),nums1.begin()+length+1); 
             nums1.insert(nums1.begin(),nums2.begin(),nums2.begin()+n+1);
         }
         return;
    }
};

3.使用双指针法

双指针法个人觉得比较较好理解,搬力扣官方解释图使用一下~

简单一点解释就是使用两个指针,分别指向nums1和nums2,依次比较两个指针所指向数组数值大小,将小的那一方放入sorted数组里就ok啦。

超时代码如下:原本是以为使用++也可以通过没想到超时,并且if条件判断的顺序也导致了超时的产生TvT。

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int p1=0,p2=0;//记得给指针赋初值
         int sorted[m+n];
         int i=0;
         while(p1<m || p2<n)
         {
           if(nums1[p1]>nums2[p2])
           {
             sorted[i]=nums2[p2++];
             i++;
           }
           else if(nums1[p1]<nums2[p2])
           {
             sorted[i]=nums1[p1++];
             i++;
           }
           if(p1==m)
           {
             sorted[i]=nums2[p2++];
             i++;
           }
           if(p2==n)
           {
            sorted[i]=nums1[p1++];
            i++;
           }
         }
         for(int t=0;t<=m+n;t++)
         {
           nums1[t]=sorted[t];
         }
         return;
    }
};

代码优化如下:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int p1=0,p2=0;//记得给指针赋初值
         int sorted[m+n];
         int a;
         while(p1<m || p2<n)
         {
           if(p1==m)
           {
             a=nums2[p2++];
           }
          else if(p2==n)
           {
            a=nums1[p1++];
           }
           else if(nums1[p1]>nums2[p2])
           {
             a=nums2[p2++];
           }
           else
           {
             a=nums1[p1++];
           }
           sorted[p1+p2-1]=a; 
         }
         for(int t=0;t!=m+n;t++)
         {
           nums1[t]=sorted[t];
         }
         return;
    }
};

4.逆向双指针

逆向双指针与方法三都是使用的指针方法,不同的地方在于,方法三顺向使用可能会有冲突,所以新建了一个数组依次存放,而通过观察可知nums1数组尾部很安全,所以使用逆向双指针节省空间。

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         int p1, p2,a,length;
         p1=m-1;
         p2=n-1;
         length=m+n-1;
         while(p1>=0 || p2>=0)
         {
           if(p1==-1)//注意是-1,因为初始赋值为m-1
           {
             a=nums2[p2--];
           }
           else if(p2==-1)
           {
             a=nums1[p1--];
           }
           else if(nums1[p1]>nums2[p2])
           {
             a=nums1[p1--];
           }
           else
           {
             a=nums2[p2--];
           }
           nums1[length--]=a;
         }
         return;
    }
};

5.使用sort()函数

代码如下:

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        nums1.erase(nums1.begin()+m,nums1.end());
        nums1.insert(nums1.end(),nums2.begin(),nums2.end());
        sort(nums1.begin(), nums1.end());
    }
};

该方法较为直接得出~

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值