【算法面试宝典】十大经典排序算法 - 归并排序

本文详细介绍了归并排序的基本原理,通过递归拆分和合并有序子数组的方法,展示了其过程。同时,讨论了算法的时间复杂度为O(NlogN),空间复杂度为O(n)。

 1 解题思路

        归并排序是使用分治策略(分治法是将大问题分成小问题,对小问题来求解,然后将分解的答案合并成大问题需要的答案)实现的排序算法,归并排序的核心思想是把数组 nums 一分为二,把分好的两个子数组分别进行排序,然后再合并两个排好的子数组得到合并后的有序数组,依次类推,直到把数组拆分的只剩一个元素,然后再依次合并。归并排序使用递归的思想,先依次拆分数组,然后再依次合并,跟快速排序某些程度上是相反的,快速排序是找目标值的位置然后拆分数组。

示例:

输入 nums = {9,4,5,2,1,7,4,6}    输出 nums = {1,2,4,4,5,6,7,9}

求解的过程如下图所示:

 可以看到这种结构很像一个完全二叉树,树的深度是 logN,本文采用递归来实现归并,所以递归的深度为 logN。

        如何合并两个有序数组?合并两个有序数组需要借助第三个数组来存储合并后的数组,假设数组 nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},两个有序数组从左往后一次比较值的大小,把值小的放入第三个数组nums3中。这些需要数组下标,假设数组 nums1 下标从 0 开始 index1 = 0,数组 nums2 下标从 0 开始,index2 = 0。 执行步骤:

第1步:index1 = 0,index2 = 0,比较 4 和 1 ,1 小于 4 ,所以把 1 放入数组 nums3 中,此时数组情况:

        nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1}

然后 index2++ = 1。

第2步:index1 = 0,index2 = 1,

        nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2}

此时 index2++ = 2。

第3步:index1 = 0,index2 = 2,

         nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3}              

此时 index2++ = 3

第4步:  index1 = 0,index2 = 3,

        nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4} 

此时 index1++ = 1

第5步: index1 = 1,index2 = 3,

        nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4,5}         

此时 index1++ = 2

第6步:index1 = 1,index2 = 3,

        nums1 = {4,5,7,8} ,nums2 = {1,2,3,6},nums3={1,2,3,4,5,6}

此时nums2已经遍历完成。

第7步:依次将 nums1 中剩下的元素插入 nums3 中  

        nums3={1,2,3,4,5,6,7,8}

第8步:把nums3中的元素按顺序放入nums中,最终得到有序数组

        nums = {1,2,3,4,5,6,7,8}

2 编码实现

    int[] tmps = new int[nums.length];

    public static void mergeSort(int[] nums,int left,int right){
        if(left<right){
            int mid = (left+right)/2;
            mergeSort(nums,left,mid);
            mergeSort(nums,mid+1,right);
            sort(nums,left,mid,right);
        }
    }

    public static void sort(int[] nums,int left,int mid,int right){
        int leftIndex = left;
        int rightIndex = mid+1;
        int tmpIndex = left;
        while(leftIndex<=mid && rightIndex<=right){
            if(nums[leftIndex] <= nums[rightIndex]){
                tmps[tmpIndex++] = nums[leftIndex++];
            } else {
                tmps[tmpIndex++] = nums[rightIndex++];
            }
        }
        while(leftIndex<=mid){
            tmps[tmpIndex++] = nums[leftIndex++];
        }
        while(rightIndex<=right){
            tmps[tmpIndex++] = nums[rightIndex++];
        }
        for(int i=left;i<=right;i++){
            nums[i] = tmps[i];
        }
    }

3 时间复杂度和空间复杂度

        由归并排序的树形结构可以看到树的深度是 logN ,每一层最多需要N次比较,所以归并排序的时间复杂度 T(n)=O(NlogN)。归并排序的时候需要使用到额外的数组tmps,所以空间复杂度 S(n) = O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值