一、归并排序原理
1.归并排序是一种分而治之的算法。其思想是将原始数组切割分成较小的数组,直到每个数组中只有一个元素,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。
2.算法分为两个函数一个是划分mergeSort,采用递归的方式将大数组分割成小数组。
划分是一个递归过程,它需要一个终止条件,就是判断数组的长度是否为一,如果是,则返回这个数组。
如果数组的长度不为一,将其继续划分为小数组,首先得找到数组的中间位mid,找到后将数组分为两个小数组left和right,left数组由索引0到mid的元素组成,right数组由索引为mid到最后一位的元素组成,继续对left和right数组调用划分函数。
3.第二个函数是归并函数merge,该函数接收两个数组作为参数,并将它们归并成一个大数组,排序发生在归并过程中。归并函数的本质就是对传进来的两个数组进行排序,并返回排序后的新数组。
4.时间复杂度O(nlog(n))
二、代码实现
const merger = (leftArr, rightArr) => {
let left_len = leftArr.length
let right_len = rightArr.length
let arr = []
let i = 0
let j = 0
while (i < left_len && j < right_len) {
leftArr[i] < rightArr[j] ? arr.push(leftArr[i++]) : arr.push(rightArr[j++])
}
while (i < left_len) {
arr.push(leftArr[i++])
}
while (j < right_len) {
arr.push(rightArr[j++])
}
return arr
}
const mergeSort = (arr) => {
let length = arr.length
if (length <= 1) {
return arr
}
let mid = Math.floor(length / 2)
let leftArr = arr.slice(0, mid)
let rightArr = arr.slice(mid)
return merger(mergeSort(leftArr), mergeSort(rightArr)); //合并左右部分
}
三、例题LeetCode148
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105
题解
该题是对链表进行归并排序,因此要在数组的基础上上升到链表,但原理是相同的。两个小链表归并可以参考LeetCode21.合并两个有序链表
以下是代码实现
var merge = function (left, right) {
var dummy = new ListNode(0, null);
var temp = dummy, temp1 = left, temp2 = right;
while (temp1 !== null && temp2 !== null) {
if (temp1.val < temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 !== null) {
temp.next = temp1;
} else {
temp.next = temp2
}
return dummy.next;
}
var mergeSort = function (head, tail) {
if (head === null) {
return head;
}
if (head.next === tail) {
head.next = null;
return head;
}
var fast = head;
var low = head;
while (fast !== tail) {
low = low.next;
fast = fast.next;
if (fast !== tail) {
fast = fast.next;
}
}
var mid = low;
return merge(mergeSort(head, mid), mergeSort(mid, tail));
}
var sortList = function(head) {
return mergeSort(head, null);
}