归并排序
归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
解析
- 先逐步进行拆分, 拆分到每一部分1个元素
- 再合并 两两比较大小 按大小排列 合并成一个升序数组
- 逐步两两合并 按大小排列 两个升序数组
- 最终得到排好序的数组
图解下
题解
- 拆分到底,合并一次后 再次对数组合并 => 递归操作很方便
- 有提到合并两个有序数组: 采用双指针的方法, 塞入新的数组中, 再对应到原数组中
代码
function sortArray(nums) {
return mergeSort(nums, 0, nums.length - 1)
}
function mergeSort(nums, l, r) {
// 拆分到一个的时候, 开始合并
if (l >= r) return nums
const mid = (l + r) >> 1
// 1. 拆分到 left/right只有一个元素的时候
// 2. 在开始合并(按照从小到大合并两个数) => 造次合并之前合后的两个(两个升序的合并)
const left = mergeSort(nums, l, mid)
const right = mergeSort(nums, mid + 1, r)
// * 合并连个升序的数组的方法
// * 双指针 指向两个升序数组 逐个比较添加 指针变动
let tmp = []
let j = 0,
p = l,
q = mid + 1
while (p <= mid || q <= r) {
if (q > r || (p <= mid && nums[p] < nums[q])) {
tmp[j++] = nums[p++]
} else {
tmp[j++] = nums[q++]
}
}
for (let k = 0; k < tmp.length; k++) {
nums[l + k] = tmp[k]
}
tmp = null
return nums
}
总结
- 合并升序数组的方法
- 双指针的使用
- 递归理解