今天刷的题目思路不难,但想把代码做得更完美还是有一定难度的。
具体题目如下:
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:
The number of elements initialized in nums1 and nums2 are m and n respectively.
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2.
Example:
Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
解答如下:
方法一
这里用了库函数sort走了捷径, 所以并不是最好的答案,还得继续探索最好的答案。代码中sort(nums1.begin(),nums1.end())默认是从小到大排序。请注意vector是向量容器,所以应该用到nums1.begin()表示向量的首地址, nums1.end()表示向量的尾地址。而数组的数组名是首地址,尾地址=首地址+数组个数。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int k = 0;
for (int i = 0; i < nums1.size(); i++)//该层for循环只为去掉nums1中的0元素
if(nums1[i] != 0 )
{
swap(nums1[k], nums1[i]);
k++;
}
k=0;
for (int i = 0; i < nums2.size(); i++)//该层for循环只为去掉nums2中的0元素
if(nums2[i] != 0 )
{
swap(nums2[k], nums2[i]);
k++;
}
nums1.resize(m+n);//将nums1按m+n的长度重置大小,用于存放所有非零元素
for (int i = m; i < m+n; i++)//将nums2中非零元素紧接着nums1中非零元素后赋值
nums1[i] = nums2[i-m];
sort(nums1.begin(),nums1.end());//将nums1按从小到大排序
}
};
提交后的结果如下:
方法二
在方法一的基础上,笔者想先把nums1和nums2直接拼接,然后通过交换的手段将所有的非0元素前移,0元素后移。最后将nums1按m+n大小重置并排序。这里有个样例比较坑:Your input:[-1,0,0,3,3,3,0,0,0] 6; [1,2,2] 3 Output:[-1,0,0,1,2,2,3,3,3].注:从样例可以知道,题目并不是要去掉所有的0元素。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int k = 0;
nums1.resize(nums1.size()+nums2.size());
for (int i = nums1.size()-nums2.size(); i < nums1.size(); i++)
nums1[i] = nums2[i-nums1.size()+nums2.size()];
for (int i = 0; i < nums1.size(); i++)
if( nums1[i] !=0 )
swap(nums1[k++], nums1[i]);
nums1.resize(m+n);
sort(nums1.begin(),nums1.end());
}
};
提交后的结果如下:
方法三:
笔者当时想到的是从头往后依次比较,而网上给出的大部分却是从后往前比较,可能是因为这样更合适吧。
解题思路: 针对nums1和nums2这两个数组我们都先从最后面的元素开始比较,找到一个较大的放到nums1中的n+m-1位置。那个较小的元素再和较大元素数组中的倒数第二个元素进行比较,之后把较大的元素放在n+m-2的位置上,依次类推,最后我们就可以得到一个排好顺序的nums1数组。
通过学习了网上关于此题的解法后,顿时发现自己由于忽视了题目中的一些条件而把题目解得复杂了。请注意条件中明确指出:①,nums1和nums2这两个数组中的元素都是已经排好顺序的(默认应该是从小到大排序,0元素不一定在最后面);②,nums1数组的位数是大于等于n+m的。因此进行两两对比后直接赋值给nums1即可,根本无需在创建一个数组来保存这些数。
//复杂容易理解版本
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i1 = m - 1, i2 = n - 1, k = m + n - 1;
while (i1>= 0 && i2>=0){
if (nums1[i1] < nums2[i2])
{
nums1[k--] = nums2[i2--];
}
else{
nums1[k--] = nums1[i1--];
}
}
while (i2 >= 0){
nums1[k--] = nums2[i2--];
}
return;
}
};
//简洁不易理解版
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i1 = m - 1, i2 = n - 1, k = m + n - 1;
while (i2 >= 0) {
nums1[k--] = i1 >= 0 && nums1[i1] > nums2[i2] ? nums1[i1--] : nums2[i2--];
}
}
};
提交后的结果如下:
日积月累,与君共进,增增小结,未完待续。