题目描述
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中*,*使得 num1 成为一个有序数组。
说明:
- 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
- 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
分析
我用了C++库函数、跟着官方题解的Java实现了一开始错了很多次的双指针。
方法一 C++库函数
需要注意的地方就是那些0,解决的方法就是从nums1的第m位开始把nums2的内容加入,这样做覆盖。我一开始的push_back的方法是不行的。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int j = 0;
for (int i = m; i < nums1.size(); i++) {
nums1[i] = nums2[j];
j++;
}
sort(nums1.begin(), nums1.end());
}
};
方法二 双指针 从头开始 来源:LeetCode 官方题解
-
tmp数组的方法就是用来保存nums1中的内容,因为它要做输出,会发生一些改变,所以用一个临时数组比较好。
-
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Object src ——— 从哪拷贝;
int srcPos ——— 从来源的哪个位置开始拷贝;
Object dest ——— 往哪里拷贝;
int destPos ——— 目标数组的起始位置;
int length ——— 拷贝多长;
-
思路就是把 tmp 和 nums2 数组中较小的那个放进结果数组 nums1 中,不够的拷贝进去。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int [] tmp = new int [m];
System.arraycopy(nums1, 0, tmp, 0, m);
int p1 = 0; // nums1 pointer
int p2 = 0; // nums2 pointer
int t = 0; // tmp pointer
while((t < m) && (p2 < n)) {
nums1[p1++] = (tmp[t] < nums2[p2]) ? tmp[t++] : nums2[p2++];
}
if (t < m)
System.arraycopy(tmp, t, nums1, t + p2, m + n - t - p2);
if (p2 < n)
System.arraycopy(nums2, p2, nums1, t + p2, m + n - t - p2);
}
}
方法三 从尾开始 有三个指针 来源:LeetCode 官方题解
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int pl = m + n - 1;
int p1 = m - 1;
int p2 = n - 1;
while ((p1 >= 0) && (p2 >= 0)) {
nums1[pl--] = (nums1[p1] > nums2[p2]) ? nums1[p1--] : nums2[p2--];
}
System.arraycopy(nums2, 0, nums1, 0, p2 + 1);
}
}
- 空间复杂度为 1,时间复杂度同解法二,m + n;
- 思路和方法二基本相同,不过起始位置是从 nums1.size() - 1处开始,这点需要注意。另外两个是从各自的 m - 1、n - 1处开始。