如何对数组的两个子有序段进行合并

问题描述:数组a[0,mid-1]和a[mid,n-1]是各子有序的,对数组a[0,n-1]的两个子有序段进行合并,得到a[0,n-1]整体有序。要求空间复杂度为O(1)(注:al[i]元素是支持‘<'运算符的)。假定给定数组a={1,5,6,7,9,2,4,6,10,13,14},mid=5,a[0]~a[4]是有序的,a[5]~a[10]是有序的,合并后的数组为{1,2,4,5,6,7,8,9,10,13,14}。


假定数组中的子有序段都按升序排列,如上例所示。下面给出在这种情况下的实现思路;

由于限定空间复杂度为O(1),因此不能使用归并排序方法。最容易想到的是插入排序方法,但这种时间复杂度为O(n^2),空间复杂度为O(1),能满足题目要求,但是由于插入排序方法没有用到各子有序的条件,因此,这种算法并不是最好的算法,下面给出另外一种方法。

实现思路:

首先,遍历数组中下标为0~mid-1的元素,将遍历到的元素的值与a[mid]进行比较,当遍历到a[i](0<=i<=mid-1)时,如果满足a[mid]<a[i],那么交换a[i]与a[mid]的值。接着找到交换后的a[mid]在a[mid,num-1]中的具体位置,实现方法为:遍历a[mid~num-1],如果a[mid+1]<a[mid],那么交换a[mid]与a[mid+1]的位置。实现代码如下:

public static void findRightPlaceForMid(int[] a,int mid){
		for(int i=mid;i<a.length-1;i++){
			if(a[i+1]<a[i]){
				int temp=a[i];
				a[i]=a[i+1];
				a[i+1]=temp;
			}
		}
	}
	public static void sort(int[] a,int mid){
		for(int i=0;i<=mid-1;i++){
			if(a[mid]<a[i]){
				int temp=a[i];
				a[i]=a[mid];
				a[mid]=temp;
				findRightPlaceForMid(a,mid);
			}
			
		}
	}
当然,如果利用归并排序,也是可以实现的,具体实现代码如下:

public static int[] merge(int[] a,int[] b){
		int aLength=a.length;
		int bLength=b.length;
		int[] arr=new int[aLength+bLength];
		int aLeft=0;
		int bLeft=0;
		int aRight=aLength-1;
		int bRight=bLength-1;
		int tmp=0;
		while(aLeft<=aRight && bLeft<=bRight){
			if(a[aLeft]<b[bLeft])
				arr[tmp++]=a[aLeft++];
			else
				arr[tmp++]=b[bLeft++];
		}
		while(aLeft<=aRight)
			arr[tmp++]=a[aLeft++];
		while(bLeft<=bRight)
			arr[tmp++]=b[bLeft++];
		
		return arr;
	}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

互联网极客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值