题目:
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]
解法1:
暴力法
设置两个指针i和j分别指向nums1和nums2
直接用nums2的每一位数字与num1相比较,
- 如果nums2的数字较小,则需插入到nums1数组中,但是在这之前需要将num1的所有数字都往后移,右移代码nums1[k] = nums1[k-1],考虑到前面的会覆盖后面的,所以我们从后往前遍历,m+j是我们已经排好的数量,所以最后一个要移动的下标为m+j-1,最前面的一个数字的下标为i,即k-1的范围为[i,m+j-1],所以k的范围为[i+1,m+j]
- 否则,i++即可
如果i == (m + j) 说明nums1的数字已经遍历完了,直接将剩下的nums2的数字插入到nums1中去即可
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = 0;
int j = 0;
while(j < n){
if(i == (m + j)){
while(j < n){
nums1[m + j] = nums2[j];
j++;
}
return;
}
if(nums2[j] < nums1[i]){
for(int k = m+j; k > i; k--){
nums1[k] = nums1[k-1];
}
nums1[i] = nums2[j];
i++;
j++;
} else {
i++;
}
}
}
};
解法2:
归并排序:
正常的归并排序需要三个数组,nums1数组,nums2数组和合并的数组
该题将nums1数组和合并数组合成一个数组,所以为了用上归并排序的思想,我们首先需要将num1中的元素先往后移n个单位,还是从最后一位m-1往前移到0,每个元素往后移n个位置
然后按正常的归并排序来做,只不过nums1从n开始,普通的归并排序最后还要检查下num1和num2剩下元素,但是在本题中只需检查num2即可,因为num1已经在合并后的数组中了
然后正常
c++:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
for(int count = 1; count <= m; count++){
nums1[m+n-count] = nums1[m-count];
}
int i = n;
int j = 0;
int k = 0;
while(i < (m+n) && j < n){
if(nums1[i] < nums2[j]){
nums1[k++] = nums1[i++];
} else {
nums1[k++] = nums2[j++];
}
}
while(j < n){
nums1[k++] = nums2[j++];
}
}
};
java中可以用System.arraycopy(nums1, 0, nums1, n, m);来实现数组的向后移n个单位
其中函数的四个参数为原数组、原数组要复制的起始位置,要复制的数组,要复制的开始位置,复制的长度
在本题中我们要将nums1中从0开始的m个元素复制到nums1中,从下标n开始
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
// for(int count = 1; count <= m; count++){
// nums1[m+n-count] = nums1[m-count];
// }
System.arraycopy(nums1, 0, nums1, n, m);
int i = n;
int j = 0;
int k = 0;
while(i < (m+n) && j < n){
if(nums1[i] < nums2[j]){
nums1[k++] = nums1[i++];
} else {
nums1[k++] = nums2[j++];
}
}
while(j < n){
nums1[k++] = nums2[j++];
}
}
}
python最后可以整体复制
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
for count in xrange(1,m+1):
nums1[m+n-count] = nums1[m-count];
i,j,k = n,0,0
while i < (m+n) and j < n:
if nums1[i] < nums2[j]:
nums1[k] = nums1[i]
i+=1
else:
nums1[k] = nums2[j]
j+=1
k+=1
if j < n:
nums1[k:] = nums2[j:]
解法3:
换一种思维我们不必要从最小的数开始归并,而是从最大的数开始归并,这样就不用将nums1中的数向后移了
c++:
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m-1;
int j = n-1;
int k = m+n-1;
while(i >= 0 && j >= 0){
if(nums1[i] > nums2[j]){
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while(j >=0){
nums1[k--] = nums2[j--];
}
}
};
java:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m-1;
int j = n-1;
int k = m+n-1;
while(i >= 0 && j >= 0){
if(nums1[i] > nums2[j]){
nums1[k--] = nums1[i--];
} else {
nums1[k--] = nums2[j--];
}
}
while(j >=0){
nums1[k--] = nums2[j--];
}
}
}
注意python列表前闭后开,所以最后nums1[:k+1] = nums2[:j+1]
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
i,j,k = m-1,n-1,m+n-1
while i >=0 and j >= 0:
if nums1[i] > nums2[j]:
nums1[k] = nums1[i]
i-=1
else:
nums1[k] = nums2[j]
j-=1
k-=1
if j >= 0:
nums1[:k+1] = nums2[:j+1]