兩個有序陣列如何合併成一個有序陣列

小珥_Boy發表於2019-03-15

我這裡考慮的兩個陣列均是升序排序,當然降序的兩個陣列進行合併演算法是類似的。

下面有兩段相似的程式碼,第一段除了返回合併後的有序陣列還將這兩個有序陣列清空了,該演算法的思路是始終比較兩個陣列的首元素大小,然後將小者 shift 出來 push 到結果陣列中去,因為總是會將陣列首元素較小的那個移出,故不用改變比較陣列的索引值,一直固定為 0 就行了。最後不要忘記將長度值大於 0 的陣列中的元素移出放置到結果陣列中。

/* 清空了原來的兩個有序陣列 */
function mergeTwoSortedArr (arr1, arr2) {
  var retArr = [];
  /* 遍歷比較兩個陣列的首元素大小,小者 shift 出來 push 到結果陣列中去 */
  while (arr1.length > 0 && arr2.length > 0) {
    if (arr1[0] < arr2[0]) {
      retArr.push(arr1.shift());
    } else if (arr1[0] > arr2[0]) {
      retArr.push(arr2.shift());
    } else {
      retArr.push(arr1.shift());
      retArr.push(arr2.shift());
    }
  }
  /* 將陣列(最多有一個)剩餘元素移出放置到結果陣列中 */
  while (arr1.length > 0) {
    retArr.push(arr1.shift());
  }
  while (arr2.length > 0) {
    retArr.push(arr2.shift());
  }
  return retArr;
}

// 示例
var arr1 = [2, 3, 5];
var arr2 = [3, 4, 7, 9];
console.log(mergeTwoSortedArr(arr1, arr2));   // [2, 3, 3, 4, 5, 7, 9]
複製程式碼

第二段程式碼則沒有影響原來的兩個有序陣列,通過遍歷比較兩個陣列當前元素的大小,小者 push 到結果陣列中去,相應陣列索引加一,然後再進行迴圈比較。同樣,最後不要忘記將未遍歷過的陣列元素複製到結果陣列中。

/* 未對原來的兩個有序陣列做改動 */
function mergeTwoSortedArr (arr1, arr2) {
  var retArr = [];
  var len1 = arr1.length;
  var len2 = arr2.length;
  var i = 0, j = 0;
  /* 遍歷比較兩個陣列當前元素的大小,小者 push 到結果陣列中去,相應陣列索引加一 */
  while (i < len1 && j < len2) {
    if (arr1[i] < arr2[j]) {
      retArr.push(arr1[i]);
      i++;
    } else if(arr1[i] > arr2[j]) {
      retArr.push(arr2[j]);
      j++;
    } else {
      retArr.push(arr1[i], arr1[i]);
      i++;
      j++;
    }
  }
  /* 將陣列(最多有一個)剩餘元素 push 到結果陣列中 */
  for (; i < len1; i++) {
    retArr.push(arr1[i]);
  }
  for (; j < len2; j++) {
    retArr.push(arr2[j]);
  }
  return retArr;
}

// 示例
var arr1 = [2, 3, 5];
var arr2 = [3, 4, 7, 9];
console.log(mergeTwoSortedArr(arr1, arr2));   // [2, 3, 3, 4, 5, 7, 9]
複製程式碼

注:上面兩段程式碼演算法的最後一步最多還要對一個陣列進行操作——將其中的元素 push 到結果陣列中去,因為之前的迴圈終止條件就是至少有一個陣列已經遍歷結束。

相關文章