归并排序空间复杂度O(1)的实现

正常的归并排序是利用分治法,即分解,解决,合并

//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)

你可能感兴趣的:(算法)