一、题目描述
给你两个有序整数数组 nums1
和 nums2
,请你将 nums2
合并到 nums1
中,使 nums1
成为一个有序数组。
初始化 nums1
和 nums2
的元素数量分别为 m 和 n 。
你可以假设 nums1
的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2
的元素。
二、题目解析
设置两个索引 i
和 j
分别指向 nums1 和 nums2 的有效元素的尾部,从它们的尾部开始向前遍历,同时设置索引 cur
指向 nums1
的最末尾,在每次遍历过程中,比较 i
和 j
指向的元素值大小,把大的元素填充到 cur
的位置,填充完毕说明那个元素已经放置在它应该放置的位置,不需要在管它了,把 cur
向前移动,同时把 i
或者 j
向前移动,继续比较 i
和 j
指向的元素值大小,把大的元素填充到 cur
的位置。
代码
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
// 合并两个有序数组( LeetCode 88 ):https://leetcode-cn.com/problems/merge-sorted-array/
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
// 索引从有序数组 nums1 有效元素的末端开始
// 数组的下标索引从零开始计数
// 索引 0 1 2
// 数组 [ 1 , 2 , 3 ]
int i = m - 1;
// 索引从有序数组 nums2 的末端开始
int j = n - 1;
// 从有序数组 nums1 最末端的位置开始保存元素
int cur = nums1.size() - 1;
// 通过循环把 num2 的元素都移动到 num1 中
while (j >= 0) {
// 比较 num1 和 num2 中当前的元素大小
// 如果 num1 中的索引位置为 i 的元素大于 num2 中索引位置为 j 的元素
// 为了防止越界 i 必须是大于等于 0
if (i >= 0 && nums1[i] > nums2[j]) {
// 把 num1 中的索引位置为 i 的元素复制到索引为 cur 的位置
// 此时 cur 的元素已经确定下来
nums1[cur] = nums1[i];
// 接下来去确定 cur 前面一个元素应该放什么数字
cur--;
// 此时,索引 i 需要向前移动
i--;
// 否则,如果 num1 中的索引位置为 i 的元素小于或者等于 num2 中索引位置为 j 的元素
}
else {
// 把 num2 中的索引位置为 j 的元素复制到索引为 cur 的位置
nums1[cur] = nums2[j];
// 接下来去确定 cur 前面一个元素应该放什么数字
cur--;
// 此时,索引 j 需要向前移动
j--;
}
}
}
};
class Solution1 {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for (int i = 0; i != n; ++i) {
nums1[m + i] = nums2[i];
}
sort(nums1.begin(), nums1.end());
}
};
class Solution2 {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1 = 0, p2 = 0;
int *sorted = new int[m+n];//分配int型的内存空间
//int sorted[m + n];//数组的定义不推荐使用变量来定义数组大小
int cur;
while (p1 < m || p2 < n) {
if (p1 == m) {
cur = nums2[p2++];
}
else if (p2 == n) {
cur = nums1[p1++];
}
else if (nums1[p1] < nums2[p2]) {
cur = nums1[p1++];
}
else {
cur = nums2[p2++];
}
sorted[p1 + p2 - 1] = cur;
}
for (int i = 0; i != m + n; ++i) {
nums1[i] = sorted[i];
}
delete[] sorted;
}
};
class Solution3 {//O(m+n);O(1)
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int p1 = m - 1, p2 = n - 1;
int tail = m + n - 1;
int cur;
while (p1 >= 0 || p2 >= 0) {
if (p1 == -1) {
cur = nums2[p2--];
}
else if (p2 == -1) {
cur = nums1[p1--];
}
else if (nums1[p1] > nums2[p2]) {
cur = nums1[p1--];
}
else {
cur = nums2[p2--];
}
nums1[tail--] = cur;
}
}
};
vector<int> split(string params_str) {
vector<int> p;
while (params_str.find(",") != string::npos) {
int found = params_str.find(",");
p.push_back(stoi(params_str.substr(0, found)));
params_str = params_str.substr(found + 1);
}
p.push_back(stoi(params_str));
return p;
}
int main()
{
//输入,此处仅为测试,考试时为leetcode模式
string NUM1;
int m;
cin >> NUM1 >> m;
vector<int> arr1 = split(NUM1);
string NUM2;
int n;
cin >> NUM2 >> n;
vector<int> arr2 = split(NUM2);
Solution3 a;
a.merge(arr1,m,arr2,n);
cout << arr1.size() << endl;//测试
for (int i = 0; i < arr1.size(); i++) {
cout << arr1[i];
if (i != arr1.size() - 1) {
cout << ",";
}
}
return 0;
}