题目地址:力扣
解法1:双指针
以最终的nums1数组为核心,每一个位置进行判断,到底是用copy_nums1的值还是用nums2的值,直到结尾
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
if (m == 0) // 简化边界情况时候的操作
nums1 = nums2;
else {
vector<int> copy_nums1 = nums1; // 中间临时存储的数组
size_t ptr1 = 0, ptr2 = 0; // 分别指向nums1和nums2
for (size_t i = 0; i < nums1.size(); ++i)
{
if (ptr1 == m)
nums1[i] = nums2[ptr2++];
else if (ptr2 == n)
nums1[i] = copy_nums1[ptr1++];
else if (copy_nums1[ptr1] > nums2[ptr2])
nums1[i] = nums2[ptr2++];
else
nums1[i] = copy_nums1[ptr1++];
}
}
}
};
解法2:追加然后排序
这种方法也没啥好讲的,就是把nums2的元素先填到nums1的真实元素的后面(即那些用0占位的地方),然后调用sort对nums1排序即可
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for (size_t i = m, j = 0; i < (m + n); ++i, ++j)
nums1[i] = nums2[j];
sort(nums1.begin(), nums1.end());
}
};
解法3:双指针改良
由于第一种方法从需要从nums1的头开始一直遍历到尾,因此就需要一个额外的辅助数组。然而nums1的末尾都是0,我们如果从尾一直遍历到头就可以实现原地合并。因此原来是谁小谁进去,现在变为谁大谁进去。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
if (m == 0)
nums1 = nums2;
else {
int ptr1 = m-1, ptr2 = n-1;
for (int i = m+n-1; i >= 0; --i)
{
if (ptr1 == -1)
nums1[i] = nums2[ptr2--];
else if (ptr2 == -1)
nums1[i] = nums1[ptr1--];
else if (nums1[ptr1] > nums2[ptr2])
nums1[i] = nums1[ptr1--];
else
nums1[i] = nums2[ptr2--];
}
}
}
};