二路归并排序定义和原理:
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer) 的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
二路归并的分解图形数据结构非常相似二叉树结构,一般采用递归方法进行。
解析:
第一步: 分
即将数组分解成一个一个最小单元,每次分解取中间元素作为分解点,如图:
每一层切割都是在切割数组之后的结果接续切割,采用递归分解,当切割的数组还剩一个元素的时候,跳出递归
const sliceArray = function(arr) {
if (arr.length < 2) {
return arr
}
let mid = Math.floor(arr.length / 2)
let left = sliceArray(arr.slice(0, mid))
let right = sliceArray(arr.slice(mid, arr.length))
}
在切割过后,都有一次合并操作,即为治。
第二步: 治
治主要是合并数组的操作,在合并的同时进行排序。如图:
合并操作的主要思想:
开辟一个新的数组空间,设定双指针分别指向数组的开始,依次比较大小,push 进新的数组中,并控制指针的移动,当指针移动到最后,即可拼接未完成数组后面的元素(切割后的数组也是经过合并的,也就是说数组本身是排序的,当一侧指针走完后,另一侧可直接拼接在结果后面)
图解:
合并操作代码:
const mergin = function (l1, l2) {
let temp = []
while(l1.length && l2.length) {
const n1 = l1.shift()
const n2 = l2.shift()
if (n1 > n2) {
temp.push(n2)
l1.unshift(n1)
} else {
temp.push(n1)
l2.unshift(n2)
}
}
return [...temp, ...l1, ...l2]
}
完整代码:
/**
* @param {number[]} nums
* @return {number[]}
*/
const mergin = function (l1, l2) {
let temp = []
while(l1.length && l2.length) {
const n1 = l1.shift()
const n2 = l2.shift()
if (n1 > n2) {
temp.push(n2)
l1.unshift(n1)
} else {
temp.push(n1)
l2.unshift(n2)
}
}
return [...temp, ...l1, ...l2]
}
const sliceArray = function(arr) {
if (arr.length < 2) {
return arr
}
let mid = Math.floor(arr.length / 2)
let left = sliceArray(arr.slice(0, mid))
let right = sliceArray(arr.slice(mid, arr.length))
return mergin(left, right)
}
var sortArray = function(nums) {
return sliceArray(nums)
};