[路飞]_LeetCode_912. 排序数组-二路归并

165 阅读1分钟

「这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战

题目

给你一个整数数组 nums,请你将该数组升序排列。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]

示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

提示:

1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104

来源:力扣(LeetCode)leetcode-cn.com/problems/so…

解题思路

本题使用归并排序,即先递归再合并的方式。

  • 递归:把一个数组分成左右两个数组,再分别对左右两个数组做归并排序;
  • 合并:当两个数组变得有序时,再通过线性合并的方式进行合并,合并后再把排序结果复制到原数组中;

二路归并在合并的时候需求申请一块新的存储空间存放排序结果,这块存储空间可以是内存也可以是外存,当我们的内存空间不够用时,譬如待排序有40G,而我们电脑的内存只有2G,这时没办法使用快速排序等排序方法,因为快速排序是所以元素在内存中的排序,如果要实现排序就要使用外存。也因此归并排序也是大数据中排序的利器。

代码实现

var sortArray = function (nums) {
    //对数组 nums 的第 0 到最后一位进行排序
    mergeSort(nums, 0, nums.length - 1)
    return nums
};

//将待排序数组 nums 的第 l 到 r 区间进行排序
var mergeSort = function (nums, l, r) {
    //如果l大于等于r时,区间只有一个元素或没有元素,不需要排序
    if (l >= r) return

    //获取中间位置,等于 l + r 除 2
    const mid = (l + r) >> 1

    //对 nums 的 l 到 mid 区间排序
    mergeSort(nums, l, mid)
    //对 nums 的 mid + 1 到 r 区间排序
    mergeSort(nums, mid + 1, r)

    //arr 存放排序结果
    const arr = []
    //定义双指针,p1 从l开始到mid,p2 从mid+1开始到r
    let p1 = l
    let p2 = mid + 1

    while (p1 <= mid || p2 <= r) {
        //如果右边的数组已经为空,或者左边第一个元素小于右边数组的第一个元素时
        //把左边的元素加入结果中,并且左边指针后移
        //否则把右边的第一个元素加入结果中,并且右边指针后移
        if (p2 > r || (p1 <= mid && nums[p1] < nums[p2])) {
            arr.push(nums[p1++])
        } else {
            arr.push(nums[p2++])
        }
    }

    //将排序结果复制到原数组
    for (let i = l; i <= r; i++) nums[i] = arr[i - l]
}

如有错误欢迎指出,欢迎一起讨论!