问题
给你两个有序整数数组 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]
示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[i] <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
试图解答
看到题的时候,我脑内:“啊这,这不就是前几天学的归并排序吗,大概是非递归版?”
第一版提交代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=0,j=0,num=0;
while(j<n&&i<m){
if (nums1[i+j]>nums2[j])
{
for(int k=m+j;k>i+j;k--){
nums1[k]=nums1[k-1];
}
nums1[i+j]=nums2[j];
j++;
}
else{
i++;
}
}
while(j<n){
nums1[i+j]=nums2[j];
j++;
}
}
};
然后解析界面发现这不是最快的,思考了一下,是每次插入nums2的时候的循环拖了速度.
用空间换时间后,代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
short i = 0, j = 0, num = 0;
while (j < n && i < m) {
if (j + num < n&&(nums1[i + j] > nums2[j + num]))
{
num++;
}
else {
if (num) {
for (short k = m + j + num - 1; k > i + j + num - 1; k--) {
nums1[k] = nums1[k - num];
}
while (num) {
nums1[i + j] = nums2[j];
j++;
num--;
}
}
i++;
}
}
while (j < n) {
nums1[i + j] = nums2[j];
j++;
}
}
};
但是这次提交的时候leecode的测试数据换成了如下数据
[2,0]
1
[1]
1
这样的小数据反而这么多if和循环判断的代码运行起来没有优势了,所以实际上还是可以优化的,直接把参数m和n用起来,从尾部开始倒序插入排列,避免了数据的移动和计数的空间消耗,一旦n==0了就代表排序结束了.
代码如下:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
while (m && n){
if (nums1[m-1] > nums2[n-1]){
nums1[m + n-1] = nums1[m-1];
m--;
}
else{
nums1[m + n-1] = nums2[n-1];
n--;
}
}
while(n){
nums1[m + n-1] = nums2[n-1];
n--;
}
}
};
但是这样leecode反而表示我内存实际上比上两个代码多用了1m,只能说不是很懂原理