1. The subject

You are given two non-descending arrays of integers, nums1 and nums2, and two integers, m and n, representing the number of elements in nums1 and nums2, respectively.

Please merge nums2 into nums1 so that the merged array is also in non-descending order.

Note: Finally, the merged array should not be returned by the function, but stored in the array nums1. To deal with this, nums1 has an initial length of m + n, where the first m elements represent the elements that should be combined and the last n elements are 0 and should be ignored. Nums2 has a length of n.

  • Example 1:
Input: nums1 =,2,3,0,0,0 [1], m = 3, nums2 = [6] 2, n = 3 output:,2,2,3,5,6 [1] : need to merge [1, 2, 3] and [6] 2. The combined result is [1,2,2,3,5,6], where the elements in italics and bold are nums1.Copy the code
  • Example 2:
Input: nums1 = [1], m = 1, nums2 = [], n = 0 Output: [1] Description: Combine [1] and []. The combined result is [1].Copy the code
  • Example 3:
Input: nums1 = [0], m = 0, nums2 = [1], n = 1 Output: [1] Description: The arrays to be merged are [] and [1]. The combined result is [1]. Note that there are no elements in nums1 because m = 0. The only zeros left in NUMs1 are simply to ensure that the merge results can be safely stored in NUMs1.Copy the code

2. Solution 1: sort directly after merging

var merge = function(nums1, m, nums2, n) { nums1.splice(m, nums1.length - m, ... nums2); nums1.sort((a, b) = > a - b);
};
Copy the code

  • Complexity analysis:
    • Time complexity: Different browsers have different implementations of sort. The average case is O((m+n)log(m+n)).

    • Space complexity: log(m + n)

3. Solution two: double pointer method

/ * * *@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 result = []
  let nums1Index = nums2Index = 0

  while(nums1Index < m && nums2Index < n) {
    if(nums1[nums1Index] <= nums2[nums2Index]) {
      result[nums1Index + nums2Index] = nums1[nums1Index++]
    } else {
      result[nums1Index + nums2Index] = nums2[nums2Index++]
    }
  }

  while(nums1Index < m) {
    result[nums1Index + nums2Index] = nums1[nums1Index++]
  }

  while(nums2Index < n) {
    result[nums1Index + nums2Index] = nums2[nums2Index++]
  }
  
  const length = result.length
  for(let i = 0; i < length; i++) {
    nums1[i] = result[i]
  }
};
Copy the code
  • Complexity analysis:
    • Time complexity: ** O(m+n)** because at most only one num1 and num2 array is traversed

    • Space complexity: O(m+n) requires an intermediate array of length m+n

4. Solution three: Double-pointer optimization (reverse double-pointer)

/ * * *@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 nums1Index = m - 1
  let nums2Index = n - 1
  while(nums1Index >=0 && nums2Index >= 0) {
    if(nums1[nums1Index] >= nums2[nums2Index]) {
      nums1[nums1Index + nums2Index + 1] = nums1[nums1Index--]
    } else {
      nums1[nums1Index + nums2Index + 1] = nums2[nums2Index--]
    }
  }

  while(nums2Index >= 0) {
    nums1[nums2Index] = nums2[nums2Index--]
  }
};
Copy the code
  • Complexity analysis:
    • Time complexity: O(m+n) because at most only one num1 and num2 array is traversed

    • Space complexity: O(1) directly modifies the array nums1 in place, requiring no extra space.

5. To summarize

It looks like solution one is faster, but you have to look at it from a complexity perspective

  • Time complexity O((m+n)log(m+n)) space complexity log(m+n)
  • Solution 2: Time complexity O(m+n) space complexity O(m+n)
  • Solution 3: Time complexity O(m+n) space complexity O(1)

So solution three is better

Ps: But usually in the development of the amount of data will not affect the efficiency, I will use the first type, because it is too simple 😁