leetcode每天一题:【合并两个有序数组】(简单)

146 阅读2分钟

这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战

题目描述

leetcode题目地址

现在有2个整数数组nums1,nums2,都是按照递增的顺序排列的,现在需要把nums2合并到nums1中,并且是按照递增的顺序返回。

另外还有2个整数(m,n),nums1的长度是m+n,m代表的是nums1需要合并的数,其它n位都是0。 n也是nums2的长度。

注意:需要直接在nums1上面修改再返回。

举个例子:

nums1:[1,2,3,0]  m:3
nums2: [4]  n:1
合并后的nums1: [1,2,3,4]

nums1:[0]  m:0
nums2: [3]  n:1
合并后的nums1: [3]

nums1:[3]  m:1
nums2: []  n:0
合并后的nums1: [3]

思路分析

第一种方法

既然nums1后面的n位都是0,那么就可以把nums2的元素都迁移到那里,这样nums1就包含了所有需要排序的元素

然后对nums1进行sort升序排序即可。

代码如下:

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function (nums1, m, nums2, n) {
  for (let i = m; i < m + n; i++) {
    nums1[i] = nums2[m + n - i - 1]
  }
  return nums1.sort((a, b) => a - b)
};

image.png

第二种方法

因为两个数组的都是升序排序的。

我们可以建一个m+n长度的新数组,

然后把通过对nums1和nums2进行遍历,nums1的索引是i, nums2的索引是j, 元素相互比较,较小的元素存到新数组中,较小的元素的索引加一,继续和之前大的元素比较。

如果索引i加到了m的时候,就证明已经nums1已经全部遍历,后面都使用nums2的元素就行。

如果索引j加到了n的时候,就证明已经nums2已经全部遍历,后面都使用nums1的元素就行。

直到ij都分别等于m和n的时候,就退出循环,这时新数组就是排好序的。

遍历它,把它的值传给nums1即可。

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function (nums1, m, nums2, n) {
  let i = 0, j = 0, cur
  const arr = new Array(m + n).fill(0)
  while (i < m || j < n) {
    if (i === m) {
      cur = nums2[j++]
    } else if (j === n) {
      cur = nums1[i++]
    } else if (nums1[i] < nums2[j]) {
      cur = nums1[i++]
    } else {
      cur = nums2[j++]
    }
    arr[i + j - 1] = cur
  }
  for (let i = 0; i < nums1.length; i++) {
    nums1[i] = arr[i]
  }
};

image.png

第三种方法

第二种需要借助个新数组,因为如果直接在nums1上面操作,有可能会覆盖了nums1本身的元素。

第三种方法,思路和第二种方法类似,但是不需要借助新数组,直接在nums1上面操作

nums1后面的n位都是0,nums2也是n位,从后往前遍历不会出现覆盖的情况,我们可以从后往前遍历替换,元素相互比较,大的先排,直接覆盖nums1的值

先覆盖的0,然后往前遍历,如果覆盖到前面的元素的时候,当前的元素都已经迁移到后面了或者是本身覆盖本身,没有影响。

代码如下:

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function (nums1, m, nums2, n) {
  let i = m - 1, j = n - 1, cur
  while (i >= 0 || j >= 0) {
    if (i === -1) {
      cur = nums2[j--]
    } else if (j === -1) {
      cur = nums1[i--]
    } else if (nums1[i] < nums2[j]) {
      cur = nums2[j--]
    } else {
      cur = nums1[i--]
    }
    nums1[i + j + 2] = cur
  }
};

image.png