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

来源:互联网 发布:中小企业数据统计 编辑:程序博客网 时间:2024/04/29 10:31

问题描述:数组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++];elsearr[tmp++]=b[bLeft++];}while(aLeft<=aRight)arr[tmp++]=a[aLeft++];while(bLeft<=bRight)arr[tmp++]=b[bLeft++];return arr;}



0 0