LeetCode 88. 合并两个有序数组(双指针法)

88. 合并两个有序数组

双指针

思路

分别设置一个头部指针,然后依次比较大小,用一个临时数组存放较小值。肯定会有一个数组未被检测完,因为是有序的,所以依次插入即可。这里我联想到了归并算法,都有一个余数检测机制。

代码实现

class Solution
{
public:
    void merge(vector<int> &nums1, int m, vector<int> &nums2, int n)
    {
        if (!nums2.size())
        {
            return;
        }
        vector<int> temp;
        int p1 = 0, p2 = 0;
        while (p1 < m && p2 < n)
        {
            if (nums1[p1] > nums2[p2])
            {
                temp.push_back(nums2[p2]);
                p2++;
            }
            else
            {
                temp.push_back(nums1[p1]);
                p1++;
            }
        }
        while (p1 < m)
        {
            temp.push_back(nums1[p1++]);
        }
        while (p2 < n)
        {
            temp.push_back(nums2[p2++]);
        }
        int i = 0;
        while (i < m + n)
        {
            nums1[i] = temp[i];
            i++;
        }
    }
};

复杂度分析

  • 时间复杂度: O ( m + n ) O(m+n) O(m+n)
    指针移动单调递增,最多移动 m + n m+n m+n​ 次,再加上最后整个 t e m p temp temp 数组复制需要 m + n m+n m+n 次,一共 2 ( m + n ) 2(m+n) 2(m+n)

  • 空间复杂度: O ( m + n ) O(m+n) O(m+n)​​
    需要建立长度为 m+n 的中间数组

逆向双指针

思路

因为这两个数组已经排好序,我们可以把两个指针分别放在两个数组的末尾,即 nums1 的 m − 1 位和 nums2 的 n − 1 位。每次将较大的那个数字复制到 nums1 的后边,然后向前移动一位。 因为我们也要定位 nums1 的末尾,所以我们还需要第三个指针,以便复制。

这里需要注意,如果 nums1 的数字已经复制完,不要忘记把 nums2 的数字继续复制;如果 nums2 的数字已经复制完,剩余 nums1 的数字不需要改变,因为它们已经被排好序。

代码实现

class Solution
{
public:
    void merge(vector<int> &nums1, int m, vector<int> &nums2, int n)
    {
        // 后续m和n作为下标使用,所以要自减
        int pos = m-- + n-- - 1;
        while (m >= 0 && n >= 0)
        {
            nums1[pos--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--];
        }
        while (n >= 0)
        {
            nums1[pos--] = nums2[n--];
        }
    }
};

复杂度分析

  • 时间复杂度: O ( m + n ) O(m+n) O(m+n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

Guess you like

Origin blog.csdn.net/leoabcd12/article/details/120464317