两个已经排序的数组A和B,A的数组前M项有值,A的空间足够大足够大能容纳A+B中的所有元素,将B中所有元素插入A中使合并后的数组有序;
刚开始接触题就想到暴力解法,先将B加入到A的后面,然后对组合后的数组进行排序,假设A和B的长度分别是M,N,那么用快排平均也需要nlog(n)的时间复杂度;显然不是一种很好的做法;
第二种想法是再利用一个数组,然后A和B分别比较较小的元素加入到新的数组中,这样时间复杂度是O(M+N),但是空间复杂度又增加了O(M);这种也不是好办法;
第三种想法是在A的左边开始和b比较然后将B插入A中,这种算法移动元素的次数较多;移动一次的时间复杂度O(M),这种算法的时间复杂度是O(M*N);显然也不是好办法;
第四种,也是比较推荐的算法是,先算出A和B的总长度,由于数组中后面的元素是空的,可以从后往前复制,时间复杂度是O(M+N);空间复杂度是O(1);这种想法是比较好的,基于第四种算法的思想做了如下的Java实现
package design;
public class ArrayCombine {
public static void main(String args[]) throws Exception {
int[] source1 = new int[50];
source1[0] = 1;
source1[1] = 2;
source1[2] = 5;
source1[3] = 9;
source1[4] = 13;
int[] source2 = new int[] { 1, 3, 4, 8, 10 };
mergeArray(source1, source2, 5);
mergeArray(source1, source2, 100);
mergeArray(source1, null, 5);
mergeArray(null, source2, 5);
mergeArray(source1, source2, 4);
}
/**
* @param source
* @param append
* @return
*/
public static int[] mergeArray(int[] source, int[] append, int m) {
/** 先进行判空,如果都非空,长度为0可认为是正确的 */
if (source == null || append == null) {
System.out.println("有一个数组是空的");
return null;
}
/** source的长度和已有M不匹配 */
if (m > source.length) {
System.out.println("数组的长度和已有M不匹配");
return null;
}
int n = append.length;
int length = m + n;
if (source.length < length) {
System.out.println("数组1的空间不够容纳数组1和2中的元素");
return null;
}
int i = length - 1;
// M+N次运算
for (; i >= 0 && m > 0 && n > 0; i--) {
if (source[m - 1] > append[n - 1]) {
source[i] = source[m - 1];
m--;
} else {
source[i] = append[n - 1];
n--;
}
}
// 比较完剩余的元素能顺利插入
while (m > 0) {
source[i--] = source[m--];
}
while (n > 0) {
source[i--] = append[n--];
}
for (int count = 0; count < length; count++) {
System.out.println(source[count]);
}
return source;
}
}