1.题目:牛客网 NC22 (合并两个有序的数组)
描述
给出一个整数数组A和有序的整数数组B,请将数组B合并到数组A中,变成一个有序的升序数组
注意:
1.可以假设A数组有足够的空间存放B数组的元素,A和B中初始的元素数目分别为m和n,A的数组空间大小为m+n
2.不要返回合并的数组,返回是空的,将数组B的数据合并到A里面就好了
3.数组A在[0,m-1]的范围也是有序的
例1:
A: [4,5,6,0,0,0],m=3
B: [1,2,3],n=3
合并过后A为:
A: [1,2,3,4,5,6]
2.解题思路(一般解法)
把B数组合并到A数组后,形成新的大小为为m+n的A数组,对新的A数组排序。
此揭发缺点:没有用到A和B皆是升序这个特点。后面排序浪费了时间。
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
for(int i=0;i<n;i++)
A[m+i]=B[i];
//对A进行排序,冒泡排序;也可直接使用sort对A进行排序
int len=m+n;
for(int i=0;i<len-1;i++)
for(int j=0;j<len-1-i;j++)
{
if(A[j]>A[j+1])
{
int temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
};
3.解题思路(双指针尾插法)
如图所示,采用3个指针,p1指向A的尾端,即m-1处,p2指向B的尾端,即n-1处。再用一个指针p指向扩容后数组A的m+n-1处。
往左边走,是p1和p2的移动方向。
每次,比较p1和p2所指向的值,大的那一个值,放入p所指向的位置。
需要注意边界条件,比如当A指针的p1走到最边,B指针p2还没走完时,把B剩下的内容按对应位置放入A即可。
代码如下:
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
int p1=m-1,p2=n-1;
for(int p=m+n-1;p1>=0&&p2>=0;p--)
{
if(A[p1]>B[p2])
A[p]=A[p1--];
else
A[p]=B[p2--];
}
//A指针先走完的情况,B中剩余元素直接copy至A对应位置即可;
while(p2>=0)
{
A[p2]=B[p2];
p2--;
}
}
};
思考(留个简单小问题,以测试你是否理解了 ):
如代码中,为什么只考虑了A指针先走完的情况,没有考虑B指针先走完的情况?