给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。
初始化 A 和 B 的元素数量分别为 m 和 n。
示例:
输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
合并后排序
两个数组合到一起后进行排序。
- 时间复杂度:O((m+n)log(m+n)) 可以理解为快排的时间复杂度
- 空间复杂度:O(log(m+n)) 同样按照快排的复杂度来看
双指针
开辟一个新的空间,双指针从头开始,逐个比较数组的每个值,每次比较将较小的值放到新的数组中
- 时间复杂度:O(m+n) 每个元素遍历一次
- 空间复杂度:O(m+n) 开辟了新的数组空间存放排序后的值
逆向双指针
方法 2 中之所以要使用临时变量,是因为如果直接合并到数组 A 中,A 中的元素可能会在取出之前被覆盖。那么如何直接避免覆盖 A 中的元素呢?观察可知,A 的后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进 A 的最后面
public void merge(int[] A, int m, int[] B, int n) {
int ia = m - 1;
int ib = n - 1;
int curr = m + n - 1;
int v ;
while(ia >= 0 || ib >= 0){
if(ia == -1){
v = B[ib--];
}else if (ib == -1){
v = A[ia--];
}else if (A[ia] > B[ib]){
v = A[ia--];
}else{
v = B[ib--];
}
A[curr--] = v;
}
}
- 时间复杂度:O(m+n) 每个元素遍历一次
- 空间复杂度:O(1) 没有使用额外空间