返回

合并两个有序数组(易) - 双指针

前端





## 问题

在 [LeetCode](https://leetcode.com/problems/merge-sorted-array/) 上有一个经典问题:合并两个有序数组。

输入:两个有序数组 nums1 和 nums2
输出:一个有序数组,包含 nums1 和 nums2 中的所有元素


例如:

nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
输出:[1, 2, 3, 4, 5, 6]


## 解法

双指针法

双指针法是一种高效的算法,常用于处理有序数据。在合并两个有序数组的问题中,双指针法可以将时间复杂度降低到 O(m + n),其中 m 和 n 分别是两个有序数组的长度。

具体步骤如下:

1. 初始化两个指针,分别指向两个有序数组的开头。
2. 比较两个指针指向的元素,较小的元素加入合并后的数组中。
3. 将指向较小元素的指针移动到下一个元素。
4. 重复步骤 23,直到两个指针都指向各自数组的末尾。
5. 如果此时两个指针指向的元素都已加入合并后的数组,则合并完成。否则,将剩余元素加入合并后的数组中。

## 代码

```javascript
/**
 * 合并两个有序数组
 * @param {number[]} nums1 有序数组 1
 * @param {number[]} nums2 有序数组 2
 * @return {number[]} 合并后的有序数组
 */
const mergeSortedArrays = (nums1, nums2) => {
  const mergedArray = [];
  let i = 0;
  let j = 0;

  while (i < nums1.length && j < nums2.length) {
    if (nums1[i] < nums2[j]) {
      mergedArray.push(nums1[i]);
      i++;
    } else {
      mergedArray.push(nums2[j]);
      j++;
    }
  }

  while (i < nums1.length) {
    mergedArray.push(nums1[i]);
    i++;
  }

  while (j < nums2.length) {
    mergedArray.push(nums2[j]);
    j++;
  }

  return mergedArray;
};

复杂度分析

  • 时间复杂度:O(m + n),其中 m 和 n 分别是两个有序数组的长度。
  • 空间复杂度:O(m + n),因为合并后的数组需要存储 m + n 个元素。

优化

为了进一步优化双指针法,可以采用以下技巧:

  • 如果两个有序数组的长度相差较大,则可以先将较短的数组排序,然后再合并。这样可以减少比较的次数,提高算法的效率。
  • 如果两个有序数组的元素都很大,则可以将数组分成更小的子数组,然后递归地合并这些子数组。这样可以减少需要比较的元素数量,提高算法的效率。

总结

双指针法是一种高效的算法,常用于处理有序数据。在合并两个有序数组的问题中,双指针法可以将时间复杂度降低到 O(m + n),其中 m 和 n 分别是两个有序数组的长度。通过采用优化技巧,还可以进一步提高双指针法的效率。