88.合并两个有序数组

题目描述:给定两个有序整数数组 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);
    }
}

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值