题目链接
题目描述
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就就有足够的空间保存来自 nums2 的元素。
示例
示例1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6]
提示
nums1.length == m + nnums2.length == n0 <= m, n <= 2001 <= m + n <= 200-10 <= nums1[i], nums2[i] <= 10思路
思路1:合并后排序
直接将
nums2合并到nums1后面,然后重新排序。思路2:双指针
创建新的数组,依次从两个数组中取数比较大小,然后将较小的数加入新创建的数组中。
思路3:逆向双指针
在思路2的解法中,如果不创建新的数组,直接从前向后加入到
nums1中,会导致某些元素被覆盖。那有没有办法实现原地修改呢?
考虑到nums1后半部分是空的,因此我们从后向前遍历,将较大的元素加入到nums1的尾部。
下面来证明此做法的正确性:
设在遍历的某一时刻,nums1中处理过的元素个数为n-p1-1,nums2中被处理过的元素个数为m-p2-1,它们都加入到了nums1的后半部分,而在指针p1的后面,有m+n-p1-1个位置。
我们让,得到
,这是恒成立的。
因此p1后面永远有足够的空间容纳处理过的元素。题解
思路3:逆向双指针
class Solution {public:void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {int p1 = m - 1, p2 = n - 1;int tail = m + n - 1;while (p1 >= 0 || p2 >= 0) {if (-1 == p1) {nums1[tail--] = nums2[p2--];} else if (-1 == p2) {nums1[tail--] = nums1[p1--];} else if (nums1[p1] > nums2[p2]) {nums1[tail--] = nums1[p1--];} else {nums1[tail--] = nums2[p2--];}}}};
复杂度分析
思路1:合并后排序
时间复杂度:
,快排的时间复杂度
-
思路2:双指针
时间复杂度:
-
思路3:逆向双指针
时间复杂度:
- 空间复杂度:
,原地修改
