目录
1.原题链接:
2.排序:
可以把数组 nums2 里面的所有元素放到 nums1 里面,然后再对 nums1 进行排序就可以了,这里可以使用快排( 时间复杂度为O(NlogN) )。因为 nums1 有 m+n 个元素,所以总的时间复杂度为O( (m+n)log(m+n) )。
3.双指针:
如果要从左向右合并数组,为了防止存在值的覆盖,需要拷贝一个nums1数组,我们这里将其命名为copy,然后分别遍历三个数组,通过比较copy数组与nums2数组当前遍历到的元素,把更小的值放入nums1,直至nums1被遍历完。
但是,在遍历copy数组与nums数组时,可能存在一个数组已经遍历完,另一个数组还没有遍历完的情况。
这时,nums1数组还没有遍历完,后面还存在错误数据,所以需要把没有遍历的元素全部放到nums1尾部(因为没有遍历的数肯定>=已经遍历了的数)。时间复杂度为O(m+n),空间复杂度为O(m+n)。
4.代码实现:
①.C语言版:
int min(int x,int y)
{
return x<y?x:y;
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
int n1=0,n2=0,tmp=0;
int copy[m+n];
for(int i=0;i<m+n;i++)//拷贝nums1数组里面的元素到copy数组里面
{
copy[i]=nums1[i];
}
while(n1<m+n && tmp<m && n2<n)
{
nums1[n1]=min(nums2[n2],copy[tmp]);
if(nums1[n1]==copy[tmp])
tmp++;
else
n2++;
n1++;
}
//当一个数组遍历完,可能存在另一个数组没有遍历完的情况
while(n2<n)//当num2数组没有遍历完
{
nums1[n1]=nums2[n2];
n1++;
n2++;
}
while(tmp<m)//当copy数组没有遍历完
{
nums1[n1]=copy[tmp];
n1++;
tmp++;
}
}
②.C++版:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int n1=0,n2=0,tmp=0;
vector<int> copy=nums1;
while(n1<m+n && tmp<m && n2<n)
{
nums1[n1]=min(nums2[n2],copy[tmp]);
if(nums1[n1]==copy[tmp])
tmp++;
else
n2++;
n1++;
}
//当一个数组遍历完,可能存在另一个数组没有遍历完的情况
while(n2<n)//当num2数组没有遍历完
{
nums1[n1]=nums2[n2];
n1++;
n2++;
}
while(tmp<m)//当copy数组没有遍历完
{
nums1[n1]=copy[tmp];
n1++;
tmp++;
}
}
};
5.逆向双指针:
对于合并这两个非递减排列的数组,最终的结果不就是值小的在前面,值大的在后面吗,那我从左往右遍历,把值小的放前面都可以,那我试试从右向左,把值大的放后面看看可不可以。时间复杂度为O(m+n)。
6.代码实现:
①.C语言版:
int max(int x,int y)
{
return x>y?x:y;
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
if(n==0)//当nums2没有要合并的数时
return;
if(m==0)//当nums1没有要合并的数时
{
for(int i=0;i<n;i++)
{
nums1[i]=nums2[i];
}
return;
}
int n1=m-1,n2=n-1,tail=(m+n)-1;
while(n1>=0 && n2>=0)
{
//选择更大的值放入tail所指位置
if(max(nums1[n1],nums2[n2]) == nums1[n1])
{
nums1[tail]=nums1[n1];
n1--;
}
else
{
nums1[tail]=nums2[n2];
n2--;
}
tail--;
}
while(n2>=0)
{
nums1[n2]=nums2[n2];
n2--;
}
//不用判断n1是否大于等于0,因为直接在nums1上面操作的
}
②.C++版:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
if(n==0)//当nums2没有要合并的数时
return;
if(m==0)//当nums1没有要合并的数时
{
nums1=nums2;
return;
}
int n1=m-1,n2=n-1,tail=(m+n)-1;
while(n1>=0 && n2>=0)
{
//选择更大的值放入tail所指位置
if(max(nums1[n1],nums2[n2]) == nums1[n1])
{
nums1[tail]=nums1[n1];
n1--;
}
else
{
nums1[tail]=nums2[n2];
n2--;
}
tail--;
}
while(n2>=0)
{
nums1[n2]=nums2[n2];
n2--;
}
//不用判断n1是否大于等于0,因为直接在nums1上面操作的
}
};
7.提交结果:
8.读书分享:
《道德经·第三十三章》:
知人者智,自知者明。胜人者有力,自胜者强。
知足者富,强行者有志。不失其所者久,死而不亡者寿。
解释:善于了解别人的人是明智,善于了解自己的人才最聪明。
能够克服别人的人是有力量,能够克制自己的人才最强大。
知道满足的人才能富有,努力不懈的人才最有志向。
不丧失根基的人才能长久,身死而不朽的人才最长寿。
《道德经·第三十四章》:
以其终不自为大,故能成其大。
由于它不自以为伟大,所以才能成就它的伟大。