Cracking the coding interview--Q9.1

原文:

You are given two sorted arrays, A and B, and A has a large enough buffer at the end to hold B. Write a method to merge B into A in sorted order.

译文:

A和B是两个有序数组(假设为递增序列),而且A的长度足以放下A和B中所有的元素, 写一个函数将数组B融入数组A,并使其有序。


最简单的方法是开一个大小可以容纳A和B的数组C,然后像归并排序中合并两个数组一样, 按照大小顺序把数组A和数组B的元素一一地放入数组C,然后再将数组C拷贝给A。 这种方法额外地使用了O(n)的空间,显然这是没有必要的开销。由于A的大小已经足够用了, 所以直接在A上直接操作即可。

可是如果我们思维定势地对比数组A和数组B,每次取小的元素放入数组A, 这样就会发现,要放入的位置上正放着有用的元素。处理起来就麻烦了。

相反,如果我们从A和B的尾部元素开始对比,每次取大的元素放在数组A的尾部, 这样一来,要放入的位置就不会出现上面的冲突问题。当对比结束时, 即可得到一个排好序的数组A。代码如下:


package chapter_9_SortingandSearching;

/**
 * 
 * A和B是两个有序数组(假设为递增序列),而且A的长度足以放下A和B中所有的元素, 写一个函数将数组B融入数组A,并使其有序。
 * 
 */
public class Question_9_1 {
	/**
	 * @param a
	 * @param b
	 * 
	 * 开辟数据c暂存比较数据
	 * 时间复杂度为0(a + b)
	 * 空间复杂度0(a)
	 * 
	 */
	public static void mergeArray(int a[], int b[]) {
		int lena = a.length;
		int lenb = b.length;
		
		int c[] = new int[lena];
		int i = 0, j =0, k = 0;
		for(; a[i] != 0 && j < lenb;) {
			if(a[i] <= b[j]) {
				c[k++] = a[i++];
 			} else {
 				c[k++] = b[j++];
 			}
		}
		
		if(a[i] == 0) {
			while(j != lenb) {
				c[k++] = b[j++];
			} 
		} else {
			while(a[i] != 0) {
				c[k++] = a[i++];
			}
		}
		
		for(int h=0 ;h<lena; h++) {
			a[h] = c[h]; 
		}
	}
	
	/**
	 * @param a
	 * @param b
	 * 
	 * 直接从尾部比较开始,则计算两个数组的长度,就可以得知尾部a存储位置
	 * 
	 */
	public static void mergeArray2(int a[], int b[]) { 
		int len;
		int i = a.length - 1;
		int j = b.length - 1;
		while(a[i] == 0) {
			i --;
		}
		len = i + 1;
		int k = len - 1 + j; 

		for(; i >= 0 && j >= 0;) {
			if(a[i] >b[j]) {
				a[k--] = a[i--];
			} else {
				a[k--] = b[j--];
			}
		}
		
		while(j >= 0) {
			a[k--] = b[j--];
		}
	}
	
	public static void printArray(int a[]) {
		for(int i=0; a[i]!=0; i++) {
			System.out.print(" " + a[i]);
		}
	}
	
	public static void main(String args[]) {
		int a[] = new int[20];
		for(int i=0; i<10; i++) {
			a[i] = i*3+1;
		}
		int b[] = new int[]{2, 4, 15, 23};
		
		mergeArray2(a, b);
		printArray(a);
		System.out.print("\n");
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值