本文首发于我的个人博客
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
归并排序是一个典型的分治算法。
归并排序核心思想就是将数组进行二分,直到数组内只剩一个元素,之后依次合并回来。
归并的核心关键在于将问题规模缩小化以及每次合并数组时数组都已经是正序。
- 首先缩小为只有两个元素,两个元素的排序时间复杂度为 O(1)。
- 之后再将两个数组合并。合并时,每个数组都已经是正序的。这样的话,只需要依次对比左右数组的元素,就能合并为一个正序数组。这个的时间复杂度为O(n) 。
示例
归并排序的步骤如下所示:
- 首先是一步步的对半拆分,直到数组内元素为1个时结束。
- 之后是慢慢合并为一个个大数组。
图片来源于【算法】排序算法之归并排序
Code
function sortArray(nums: number[]): number[] {
if (nums.length >= 2) {
const left: number[] = sortArray(nums.slice(0, Math.floor(nums.length / 2)));
const right: number[] = sortArray(nums.slice(Math.floor(nums.length / 2), nums.length));
const ret: number[] = [];
let l: number = 0, r: number = 0;
while ( l < left.length || r < right.length ) {
if ( l === left.length ) {
ret.push(right[r]);
++ r;
continue
}
if ( r === right.length ) {
ret.push(left[l]);
++ l;
continue
}
if (left[l] > right[r]) {
ret.push(right[r]);
++ r;
}else {
ret.push(left[l]);
++ l;
}
}
return ret
}else {
return nums
}
};
复杂度分析
时间复杂度:O( n logn )。由于算法一共有 logn 层, 每层的操作数都是 n(合并有序数组的操作),因此总的时间复杂度就是 n logn。
空间复杂度:O( n + logn )。因为使用递归来完成,那么递归栈的最大长度就是 logn,再加上合并有序数组开辟的 n 的临时数组,总共是 n + logn。