合并两个有序数组为一个新的有序数组

简便做法

// 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())

这其实是归并排序的一个核心细节。

posted @ 2020-09-25 00:53  oceans-pro  阅读(730)  评论(0编辑  收藏  举报