归并两个已排序数组为一个数组,不同于归并排序的归并用一个额外的数组,这里在第一个数组预留出足够的空间,所以需要直接在第一个数组里存放原来的两个数组的所有元素。
归并排序里,是额外开一个数组,然后两个指针分别从第一个数组和第二个数组的开头进行比较,比较小的那一个元素加入新数组中,然后某个数组为空之后,把另一个数组剩下的所有元素加入到新数组中。
这个过程结束之后,新数组就是归并之后的两个数组。
不过在这题里,从头开始比较两个数组,然后再把元素放入nums1里,会覆盖nums1原本的元素,不可行。
正好nums1后面预留出的元素全是0,是可以覆盖掉的,所以这题需要分别从nums1和nums2的末尾开始比较,较大的那个元素放到末尾,然后指针向前。
代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1, j = n - 1, k = m + n - 1; //指针i指向原来nums1的有效元素的(不包括0)末尾,从后往前寻找最大的元素, 指针j指向nums2的末尾
while(i >= 0 && j >= 0) {
if(nums1[i] >= nums2[j]) { //较大的那个数加入到nums1的末尾
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while(j >= 0) { //如果nums1为空,nums2不为空,则说明剩下的nums2是归并后的数组最小的部分,加入到nums1中
nums1[k--] = nums2[j--]; //不需要判断nums1为空的情况,因为如果i >= 0,说明nums2已经放到了它们应该放的位置,nums1的元素现在的位置就是它们最终的位置,不用动!
}
}
};