题目
给你两个按 非递减顺序 排列的整数数组 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());
}
};
该方法较为直接得出~