题目要求:合并两个已有序序列为A[0…i],A[i+1…N-1] 为A[0...N-1], 要求不用或者只使用常量辅助空间
为叙述方便,表示A[0…i]为a[0..n-1],A[i+1…N-1]为b[0…m-1],问题实际上是使用常数辅助空间的归并排序
不用辅助空间的归并排序
思路如下:如果a[0] 小于b[0],问题变为合并a[1..n-1]和b[0…m-1],还是同一个问题迭代解决
否则,即a[0]大于b[0],交换两个元素,此时b[0]可能大于b[1], 用冒泡排序的方法将b[0]向右移动合适的位置,接下来问题也变为合并a[1..n-1]和b[0…m-1],迭代解决。
复杂度分析:考虑一种极端情况,前半部分的元素全部大于后半部分,即a中的所有元素都大于b中的元素,这时以第一个元素为例,比较次数为1+(m-1)=m, m-1次为冒泡移动的比较次数,所以合并的复杂度为m+(m-1)+(m-2)+..=1= m*(m+1)/2,在此说明,这时一种极端情况。当前部分元素完全小于后部分是,则元素比较次数为n。如果一个完整的归并排序使用这种方法,则最坏复杂度为T(n)=2T(n/2)+ (n/2)*(n/2 +1)=2T(n/2) + n(n+1)/4,取极限为n(n+1)/2,即此时归并排序的复杂度和冒泡排序已经一样,从这一点来看和快排还是很相似的。
使用k个辅助空间的归并排序,k远远小于元素数目,辅助数组为c[k]
原理类似,将a[0…k-1]移到c[0…k-1]中,然后用常规方法将b[0..m-1]和c[0…k-1]归并k个元素到位置a[0…k-1],比较次数为k,假设此时数组c中剩余的元素为c[t…k-1],则此时数组b中前端必然也空出了k—t个位置,即b[0..k-t-1]必然没有元素。接下将b[k-t…m-1]和c[t…k-1]归并到b中的前端空位,比较次数最多为m, 数组c变为空,现在问题变成了归并a[k…n-1] 和b[0…m-1]了,迭代解决,注意终止条件。
复杂度分析:每次迭代的最多比较次数为将k+m,一共有n/k次迭代,所以总复杂度为(k+m)*(n/k)=n+(nm)/k,当k=n时即是原来的归并排序复杂度(nlogn),当k=1时即为不用辅助空间的排序复杂度n^2。
再次说明,上述的n^2复杂度都是基于初始序列完全逆序的极端情况,个人认为,平均情况下使用辅助空间的渐进复杂度复杂度应该也是对数级。