归并排序和一些例题

归并排序的原理并不是很复杂,他的意思是说,将一个数组从中间分解成左右两个部分,然后对左右两部分分别排序,将排序后的结果再进行合并。

我们先来讨论经典的递归实现方法。

归并排序的递归实现可以总结为:左边排好序+右边排好序+merge让总体有序

这个问题最大的困难就是如何进行合并merge,我们通过画递归树可以知道,最后一定是一个元素和一个元素进行的merge,那么这个merge的过程还需要涉及到对这两个元素进行比较,那么如何去实现呢?

这里我们采用双指针法和辅助数组的方式,首先创建一个辅助数组,左右两个元素分别创建辅助指针,如果左边的元素小,先进入数组,后移,右边的小右边的先进,后移,同样大小,左边的进去,同时后移。

        

 

 

归并排序的复杂度是O(NlogN)

merge过程两个指针都没有回退, 是O(N)

比较行为每一次变成结果再传递, 没有浪费(相比N^2的算法)

为什么比O(N^2)的排序好,最本质的原因是所有O(N^2)的排序,大量浪费比较行为比较行为都是独立的. 上一次发生的比较行为,丝毫不能够加速底下的比较行,大量浪费比较行为

与 插入, 冒泡, 选择等N^2排序的比较

选择等每次排序相对独立,大量浪费比较行为

把有序部分规定/留下来, 没有浪费比较行为

而归并排序 我左组内部的比较行为浪费了吗?没浪费, 都变成了排序好的结果,右侧部分也变成了排序好的结果。当你左侧跟右侧Merge的过程中,左组数之间是根本没有比较的,要比较是左组某一个指针对右组某一个指针在比较,你们此时比较行为也没有浪费, 变成了你们共同的一个排好序的结果,所以比较行为每一次都变成结果在传递,所以复杂度是O(N*logN)

额外空间复杂度为O(N)

现在看看代码

class MergeSort{
    public static void mergeSort(int[] arr){
        if(arr == null || arr.length < 2){
            return;        
        }
        process(arr,0,arr,length - 1);
    }
    public static void process(int[] arr,int left,int right){
        if(right == left){
            return ;        
        }    
        int mid = left + ((right - left) >> 1);
        process(arr,left,mid);
        process(arr,mid+1,right);
        merge(arr,left,mid,right);
    }
    public static void merge(int[] arr,int left,int mid,int right){
        int[] help = new int[right - left + 1];
        int p1 = left;
        int p2 = mid + 1;
        int i = 0;//用于记录数组位置
        while(p1 <= mid && p2 <= right){
            help[i++] = arr[p1] >= a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值