算法分析:合并两个有序数组

目录

  • 前言
    • 第一种方法:暴力解法
    • 第二种解法:归并排序
    • 第三种解法:优化归并排序
  • 总结

前言

  • 这道题目说实话看起来很简单,就是把两个数组按顺序排序到一个新的数组里面,然后这两个数组还是有序的,但是这里面还有有学问的,一共三个方法,每个方法都是前面一个方法的进阶,所以还是很有讲究的。
  • 题目网址:https://leetcode-cn.com/problems/merge-sorted-array/
    算法分析:合并两个有序数组_第1张图片

第一种方法:暴力解法

  • 这种方法简单粗暴,就是把两个数组放到一起,然后直接进行排序。
  • 不多说直接上代码:
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        System.arraycopy(nums2,0,nums1,m,n);
        Arrays.sort(nums1);
    }
}

//普及一下这个方法
public static void arraycopy(Object src,
                             int srcPos,
                             Object dest,
                             int destPos,
                             int length)
意思是;将 src 数组里从索引为 srcPos 的元素开始, 复制到数组 dest 里的索引为 destPos 的位置, 复制的元素个数为 length 个. 

算法分析:合并两个有序数组_第2张图片

第二种解法:归并排序

  • 第一种解法直接简单粗暴,但是时间上还是相对于差一点,所以我们利用空间换时间的做法,通过遍历一遍就可以完成。

  • 而这种解法也就是归并排序的思想,意思是重新创建一个可以容纳下nums1 和 nums2 的数组,然后通过一起遍历判断完成合并

  • 第一步:创建一个 nums1 的数组大小的数组 nums1_copy
    算法分析:合并两个有序数组_第3张图片

  • 第二步,将两个指针指向nums1 和 nums2,然后进行遍历
    算法分析:合并两个有序数组_第4张图片

  • 第三步,将两个指针指向的数字进行判断,哪一方小就把哪一方放入第三个数组的指定索引中
    算法分析:合并两个有序数组_第5张图片
    算法分析:合并两个有序数组_第6张图片
    算法分析:合并两个有序数组_第7张图片

算法分析:合并两个有序数组_第8张图片

  • 第四步,当一组数组循环遍历完之后,判断剩下的数组还有没有数字,如果有就复制到剩下的位置
    算法分析:合并两个有序数组_第9张图片
  • 这样就解决了,不说了看代码
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] nums = new int[m];
        System.arraycopy(nums1,0,nums,0,m);
        //指向nums1的指针
        int p = 0;
        //指向nums的指针
        int p1 = 0;
        //指向nums2的指针
        int p2 = 0;
        while(p1 < m && p2 < n){
            nums1[p++] = nums[p1] < nums2[p2] ? nums[p1++] : nums2 [p2++];
        }
        if(p1 < m){
            System.arraycopy(nums,p1,nums1,p1+p2,m+n-p1-p2);
        }
        if(p2 < n){
            System.arraycopy(nums2,p2,nums1,p1+p2,m+n-p1-p2);
        }
    }
}

算法分析:合并两个有序数组_第10张图片

第三种解法:优化归并排序

  • 上面一种方法一看性能提升了很高,但是空间换时间的做法确实有点亏,而这道题本身就给予我们更多的空间的数组,所以我们可以取巧,不需要再创建数组,直接将索引放在 nums1 的后面从后往前判断。
    算法分析:合并两个有序数组_第11张图片
  • 遍历就不再画图了,直接上代码把
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        //指向nums1的尾指针
        int p = nums1.length-1;
        //指向nums1的指针
        int p1 = m-1;
        //指向nums2的指针
        int p2 = n-1;
        while(p1 >= 0 && p2 >= 0){
            nums1[p--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2 [p2--];
        }
        System.arraycopy(nums2,0,nums1,0,p2+1);
    }
}

算法分析:合并两个有序数组_第12张图片

总结

曾经我同学碰到这个问题,因为面试官直接让他用归并排序来完成,把他吓了一跳,因为归并排序本来就比较繁琐,所以他一紧张就没写出来,他来问我,我也懵逼,但是我今天才发现这题原来这么简单,我的天错失良机,所以还是要多学习。

你可能感兴趣的:(算法分析,指针,数据结构,leetcode,java,算法)