规定了时间我首先想到的是归并排序,以时间换空间,题目要求时间复杂度O(m+n)
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-109 <= nums1[i], nums2[j] <= 109
而且这个题理论上,是合并,所以得把最后合并的结果放到nums1[]上
下面是代码
java
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
vector<int> temp(nums1.begin(),nums1.begin()+m);
int p=0;
int p1=0;
int p2=0;
while(p1<m&&p2<n){if(temp[p1]<=nums2[p2])
nums1[p++]=temp[p1++];else
nums1[p++]=nums2[p2++];
}
while(p1<m)nums1[p++]=temp[p1++];
while(p2<n)nums1[p++]=nums2[p2++];
}
};
然后再复习一下归并排序
这么多年了,发现自己学习算法过于死板
其实归并排序是一棵归并排序二叉树。
那么一涉及到树就很容易理解,这里头有递归,所以归并排序是由递归和merge函数组合来实现的,那个大的递归函数就是
java
void mergeSort(vector<int>& arr, int l, int r){
if(l>=r) return;
int mid=(l+r)/2;
mergesort(arr,l,mid);
mergesort(arr,mid,r);
merge(arr,l,mid,r);
}
下面是完整的归并排序的代码
java
#include <iostream>
#include <vector>
using namespace std;
// 合并两个有序区间 [l, mid] 和 [mid+1, r]
void merge(vector<int>& arr, int l, int mid, int r) {
vector<int> temp(r - l + 1);
int i = l;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= r) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while (i <= mid) temp[k++] = arr[i++];
while (j <= r) temp[k++] = arr[j++];
// 复制回原数组
for (int p = 0; p < temp.size(); ++p) {
arr[l + p] = temp[p];
}
}
// 归并排序递归
void mergeSort(vector<int>& arr, int l, int r) {
if (l >= r) return;
int mid = (l + r) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r);
merge(arr, l, mid, r);
}
int main() {
vector<int> arr = {5, 2, 9, 1, 5, 6, 3, 8};
cout << "排序前:";
for (int x : arr) cout << x << " ";
cout << endl;
mergeSort(arr, 0, arr.size() - 1);
cout << "排序后:";
for (int x : arr) cout << x << " ";
cout << endl;
return 0;
}
直接从后面替换插入的方法
java
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i=nums1.size()-1;
n--;
m--;
while(n>=0){
while(m>=0&&nums1[m]>nums2[n]){
swap(nums1[i--],nums1[m--]);
}
swap(nums1[i--],nums2[n--]);
}
}
};