正常的归并排序是利用分治法,即分解,解决,合并
//O(n)Membery mergeSort
public void mergeSort(int[] nums)
{
int n = nums.length;
helper(nums, 0, n-1);
}
private void helper(int[] nums1,int b, int e)
{
if(b < e)
{
int mid = (b + e) >> 1;
helper(nums1, b, mid);
helper(nums1, mid+1, e);
merge(nums1, b,mid,e);
}
}
void merge(int[] nums1,int b, int m,int e)
{
int[] nums2 = new int[nums1.length];
int i = b, j = m + 1, k = b;
while(i <= m && j <=e)
{
if(nums1[i] <= nums1[j]){nums2[k++] = nums1[i++];}
else nums2[k++] = nums1[j++];
}
while(i <= m){nums2[k++] = nums1[i++];}
while(j <= e){nums2[k++] = nums1[j++];}
for(int ii = b; ii <=e; ii++)
{
nums1[ii] = nums2[ii];
}
}
显然利用临时数组,空间复杂度为O(N)
倘若在merge操作时,可以只使用O(1)的空间。
答案是可以的!!
首先让我们熟悉一下旋转的操作。
旋转:
比如: abcdefg 以d为轴心旋转,得到efgabcd,可以通过如下算法实现。
步骤1:对abcd和efg进行reverse ,得到dcba gfe
步骤2:对整体进行reverse,即得到结果 efg abcd
在merge时:
比如:2468 3578 L1:2468 L2:3578,要将L1和L2合并
步骤:
1、确定3在整体中的位置,即在2和4之间。
2、对 468 3进行上述旋转操作
1、各自reverse 864 3
2、整体reverse 3 468
3、repeat 直至数组越界。
T(n) = 2T(n/2)+O(2n)
O(nlg2n)