题目描述:给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:初始化 nums1 和 nums2 的元素数量分别为 m 和 n。你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3输出: [1,2,2,3,5,6]
方法一:合并后排序
将数组 2 复制到数组 1 后面,然后进行排序。但是没有利用到数组是有序的这个条件。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for(int i = 0,j = m;i < n;i++,j++){
nums1[j] = nums2[i];
}
// 插入排序
for(int i = 1;i < m+n;i++){
int val = nums1[i];
int j = i - 1;
for(;j >= 0 && val < nums1[j];j--){
nums1[j+1] = nums1[j];
}
nums1[j+1] = val;
}
}
}
方法二:双指针法 - 从前往后
一、新开辟空间
由于最后结果放在 nums 1 中,所以先将 nums 1 复制一份,然后两个变量 i,j 分别从 复制的nums1 与 nums2 的起始元素开始比较大小,将较小的放入 nums 1 中,直至有一个数组遍历结束。然后判断是否有数组还有剩余元素,直接拷贝到 nums1 后面。
class Solution {
// 时间复杂度O(n+m),空间复杂度均为 O(m)
public void merge(int[] nums1, int m, int[] nums2, int n) {
int[] copyArray = new int[m];
System.arraycopy(nums1,0,copyArray,0,m);
int i = 0,j = 0,index = 0;
while(i < m && j < n){
nums1[index++] = (copyArray[i]<=nums2[j]) ? copyArray[i++] : nums2[j++];
}
if(i == m){
System.arraycopy(nums2,j,nums1,index,n-j);
}
if(j == n){
System.arraycopy(copyArray,i,nums1,index,m-i);
}
}
}
二、不开辟空间,在原数组上移动
两个变量同时在从前面开始,从第一个数组中找到第二个数组元素的合适位置做插入,插入之前要将数组一的相应元素后移。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = 0,p2 = 0,count = 0;
while(p2 < n){
if(!(nums1[p1] <= nums2[p2] && p1 < m+count)){
for(int i = m+count;i > p1;i--){
nums1[i] = nums1[i-1];
}
nums1[p1] = nums2[p2];
p2++;
count++;
}
p1++;
}
}
}
方法三:双指针法 - 从后往前
两个变量 i,j 分别指向两个数组的最后一个元素,而变量 index 表示最终数组的最后一个元素位置。不断比较 nums1[i] ,nums2[j] 的值,将较大的数放到 index 位置,结束条件就是两个数组至少有一个遍历完了。如果遇到下面这种情况:
nums1:{4,5,0,0} ,nums2:{1,2} 在遍历结束后的 num1:{4,5,4,5},就要将 nums2 的元素全部移到 nums1 的前面。
但不用担心 nums1 的元素有没有漏掉的,因为数组的修改是在 nums1 的基础上进行修改,如果 nums2 的值已经全部放在 nums 1 中,那么 nums1 其余的元素一定在原位置不需要改变。
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m - 1,j = n - 1,index = n+m-1;
while(i>=0 && j>=0){
nums1[index--] = (nums1[i] > nums2[j]) ? nums1[i--] : nums2[j--];
}
System.arraycopy(nums2,0,nums1,0,j+1);
}
}