簡便做法
// 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())
這其實是歸並排序的一個核心細節。