30

合并两个有序数组

 3 years ago
source link: http://www.cnblogs.com/ruoli-0/p/13697737.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

题目来源: 力扣(LeetCode)

题目详情:

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。

你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入:

nums1 = [1,8,9,15,0,0,0,0,0], m = 4

nums2 = [2,5,6,12,18], n = 5

输出: 

[1,2,5,6,8,9,12,15,18]

解法一:

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] result = new int[m+n];      // 创建一个大小为m+n的数组,确保装的下所有排序的元素
        int i = 0;
        int j = 0;
        int k = 0;
        while(i < m && j < n){          // 从左往右,往result中装数据
            if(nums1[i] <= nums2[j]){
                result[k++] = nums1[i++];
            }else{
                result[k++] = nums2[j++];
            }
        }
        while(i < m){            // 将nums1中剩余元素加到result后面
            result[k++] = nums1[i++];
        }
        while(j < n){            // 将nums2中剩余元素加到result后面
            result[k++] = nums2[j++];
        }
        for(int s = 0; s < result.length; s++){  // 将排好序的result拷贝给nums1
            nums1[s] = result[s];
        }
    }
}

这种解法很简单,也很容易理解。就是 额外创建一个数组result数组的大小为m + n 即所有排序元素的个数,用来 往里面 从左到右、 从小到大装数据 。创建 三个指针i 指向数组nums1的第一个元素j 指向数组nums2的第一个元素k 指向数组result的第一个位置。

比较nums1和nums2 的指针所指向的 当前元素的大小小的填入到result中 k 指向的位置 ,此时 两个指针都向前移动一位重复当前操作 —— 填数据

直到nums1和nums2其中一个数组遍历完了 ,此时 另一个未遍历完的数组剩余的数都大于result中的元素将这些数依次加到result后面。

到现在我们得到了 一个已经 包含 nums1和nums2中 所有元素的排好序的数组result 是还 没有结束 ,因为我们所要做的是 合并两个数组 ,也就是 将nums2合并到nums1中最后nums1是一个合并好的、排好序的数组 ,我们当前的nums1还不是。 所以 ,我们 还要更新一下nums1将result中的元素拷贝到nums1中至此nums1才是题目要求的样子

7j6Fb2Y.png!mobile

解法二:

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int len1 = m - 1;
        int len2 = n - 1;
        int len = m + n - 1;
        while(len1 >= 0 && len2 >= 0) {
            nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
        }
        // 将nums2数组从下标0位置开始,拷贝到nums1数组中,从下标0位置开始,长度为len2+1
        System.arraycopy(nums2, 0, nums1, 0, len2 + 1);

    }
}

这种方法相对巧妙一点,没有额外的创建数组, 减少了算法的空间复杂度 。让我们来看一看这种解法的思路是什么吧。

解法一的思路是从小到大填数,以此相反,这种解法是 从大到小填数据 ,是 在数组nums1上从后往前填数选择大的填

while循环中,当数组nums2中的元素都被填完后,nums1就排好序了当nums1中的元素被填完,而nums2中的元素还有一些时 ,语句  System.arraycopy(nums2, 0, nums1, 0, len2 + 1); 就发挥作用了, 会将nums2中剩余的元素加到nums1中使得nums1合并排序完成。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK