解析
- 分解子问题:将需要被排序的数组从中间分割为两半,然后再将分割出来的每个子数组各分割为两半,重复以上操作,直到单个子数组只有一个元素为止。
- 求解每个子问题:从粒度最小的子数组开始,两两合并、确保每次合并出来的数
答案
function mergeSort(arr) {
const len = arr.length
if (len <= 1) {
return arr
}
const mid = Math.floor(len / 2)
const leftArr = mergeSort(arr.slice(0, mid))
const rightArr = mergeSort(arr.slice(mid, len))
arr = mergeArr(leftArr, rightArr)
return arr
}
function mergeArr(arr1, arr2) {
let i = 0,
j = 0
const res = []
const len1 = arr1.length
const len2 = arr2.length
while (i < len1 && j < len2) {
if (arr1[i] < arr2[j]) {
res.push(arr1[i])
i++
} else {
res.push(arr2[j])
j++
}
}
if (i < len1) {
return res.concat(arr1.slice(i))
} else {
return res.concat(arr2.slice(j))
}
}
复杂度
- 我们把每一次切分+归并看做是一轮。对于规模为 n 的数组来说,需要切分 log(n) 次,因此就有 log(n) 轮。
- 单次合并的时间复杂度为 O(n)
- log(n) 轮对应 log(n) 次合并操作,因此归并排序的时间复杂度就是 O(nlog(n))。