合并两个有序数组

224 阅读2分钟

1.

结合 Leetcode 中的第 88 题 《合并两个有序数组》,通过利用数组的多个改变自身的方法来解决。题目如下:

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
  输入:
  nums1 = [1,2,3,0,0,0]; m = 3
  nums2 = [2,5,6];       n = 3
  输出: [1,2,2,3,5,6]

仔细看下题目要求:

  • 是将 nums2 合并到 nums1 里面,不新开数组;
  • 其次是合并完之后 nums1 还是一个有序数组;
  • 对于样例里面数组 nums1 和 nums2 重复的数“2”,重复的也要合并进去。
var merge = function(nums1, m, nums2, n) {
    nums1.splice(m);
    nums2.splice(n);
    nums1.push(...nums2);
    nums1.sort((a,b) => a - b);  
    return nums1;
};
console.log(merge(nums1,m,nums2,n));   //[ 1, 2, 2, 3, 5, 6 ]  

注意:nums1.push(...nums2);

  • 如果用 push 和 (...) 把数组nums2添加进数组nums1,可以直接用return返回最终的结果;
  • 如果用 concat 拼接两个数组,需要用变量去承接拼接后的数组,nums1 = nums1.concat(nums2); return nums1.sort((a, b) => a - b)。

原因在于,push() 是会改变数组自身值的方法,concat() 不会改变自身。可以直接执行nums1.concat(nums2); 并在排序完成后直接返回观察变化。

2.

合并两个有序数组arr1,arr2,可以新开数组arr3返回结果

方法一

const arr1 = [1, 3, 5, 7, 9]
const arr2 = [2, 4, 6, 8, 10, 12, 14, 16]

function concat(a1, a2) {
    const a3 = [...a1, ...a2];
    function swap(myArray, p1, p2) {   //交换位置
        var temp = myArray[p1]   
        myArray[p1] = myArray[p2]
        myArray[p2] = temp
    }
    function bubbleSort(myArray){   //冒泡排序
        var len = myArray.length - 1
        var i
        var j
        for(i = 0; i < len; i++){
            for(j = 0; j < len - i; j++){
                if(myArray[j] > myArray[j + 1]){
                    swap(myArray, j, j + 1)
                }
            }
        }
        return myArray
    }
    return bubbleSort(a3)
}

const arr3 = concat1(arr1, arr2)
console.log(arr3);   //[1, 2, 3,  4,  5,  6, 7, 8, 9, 10, 12, 14, 16]

方法二

//方法二
const arr1 = [1, 3, 5, 7, 9]
const arr2 = [2, 4, 6, 8, 10, 12, 14, 16]

function concat1(a1, a2) {
    // 1. 创建空数组
    const a3 = [];
    let i = 0, j = 0;
    // 2. 循环,比较元素大小
    while(i < a1.length) {
        //当其中一个数组被遍历完后结束循环
        if (!a1[i] || !a2[j]) break;  
        if (a1[i] < a2[j]) {
            a3.push(a1[i]) 
            i++;
        } else {
            a3.push(a2[j])
            j++;
        }
    }
    //3. 将剩下数组中未完成遍历的元素添加进去
    if (i === a1.length) {
        // 追加a2剩余元素
        a3.push(...a2.slice(j,a2.length))
        
    }
    if (j === a2.length) {
        // 追加a1剩余元素
        a3.push.apply(a3, a1.slice(j,a1.length))
    }
    //返回结果数组
    return a3
}

const arr3 = concat1(arr1, arr2)
console.log(arr3);

注意,在执行第三步过程中,如果直接用push追加元素,会出现以下结果:
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, [ 10, 12, 14, 16 ] ]

解决方法有:

  • 用concat拼接数组----a3.concat(a2.slice(j,a2.length))
  • 用展开语法(...)----a3.push(...a2.slice(j,a2.length))
  • 用apply指向a3---- a3.push.apply(a3, a1.slice(j,a1.length))

方法三

Array.prototype.range = function (start, end) {
      var _self = this
      var length = end - start + 1
      var step = start - 1
      return Array.apply(null, { length: length }).map(function (v, i) {
        step++
        return step
      })
    }
    
    const arr1 = [1, 3, 5, 7, 9]
    const arr2 = [2, 4, 6, 8, 10, 12, 14, 16]
    
    function concat(a1, a2) {
      const a3 = [...a1, ...a2]
    
      const min = Math.min(...a3)
      const max = Math.max(...a3)
      const t = [].range(min, max)
    
      let a4 = t.filter(item => {
        return a3.includes(item)
      })
      return a4
    }
    
    console.log(concat(arr1, arr2))