合并两个有序数组Java实现

两个已经排序的数组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;
	}
}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值