合并两个有序数组为一个新的有序数组
简便做法
// log
let arr1 = [1, 2, 3, 4, 5, 6, 7] // m个
let arr2 = [2, 3, 4, 7, 10, 19, 39] // n个
let arr = arr1.concat(arr2)
arr.sort((a, b) => a - b)
console.log(arr.join())
注意这里有个坑...如果只用 arr.sort()不传入函数的话,是按照 ASCI 码进行排序的,即
// log
let arr1 = [1, 2, 3, 4, 5, 6, 7] // m个
let arr2 = [2, 3, 4, 7, 10, 19, 39] // n个
let arr = arr1.concat(arr2).sort().join()
console.log(arr)
sort 方法内部使用的排序算法为快速排序
或选择排序
(小数组),更多细节可以参考深入了解 javascript 的 sort 方法。因此上述简便做法的时间复杂度为O(n*log(n))
或O(n^2)
。
降低时间复杂度的一个算法
考虑到两个数组是有序的,为了提高性能,考虑如下场景:两个班级合并为一个班级,同学的名次要发生变更(原先在 A 班第一名的小丽,可能连前三名都进不了)。班主任按照如下步骤进行操作:
- 每轮两班选出各自班级排名最靠前的同学进行比较。(数组的第一个)
- 选出的代表再比较他们的真实成绩(数值),成绩好的人的名字写在一个本子上(一个新的数组),并将名字从原班级划掉
- 若干轮后(不超过 m+n),其中一个班级的学生的名字都被划掉了。
- 此时再把另外一个班级没有写在本子上的同学,依名次写入到本子上。
将上述算法转化为代码,如下所示
/**
* 合并两个有序数组为一个新的有序数组
* 时间复杂度 O(m+n)
* @param {Array<Number>} arr1
* @param {Array<Number>} arr2
*/
function joinAndSortTwoSortedArray(arr1, arr2) {
let arr = []
let flag1 = 0
let flag2 = 0
let len = arr1.length < arr2.length ? arr1.length : arr2.length
while (arr1.length > 0 && arr2.length > 0) {
if (arr1[flag1] > arr2[flag2]) {
arr.push(arr1.shift())
} else {
arr.push(arr2.shift())
}
}
arr = arr.concat(arr1, arr2)
return arr
}
let arr1 = [100, 99, 98, 90, 80, 76, 60, 50]
let arr2 = [92, 89, 80, 70, 49, 39]
let res = joinAndSortTwoSortedArray(arr1, arr2)
// log
console.log(res.join())
这其实是归并排序的一个核心细节。