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

来源:互联网 发布:大数据分析系统架构 编辑:程序博客网 时间:2024/05/21 10:37

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

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

2 0
原创粉丝点击