算法-数组-合并两个有序数组

232 阅读1分钟

这是我参与更文挑战的第2天,活动详情查看: 更文挑战

题目

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

方法一

因为nums1数组一定有足够的空间,所以通过遍历nums2数组元素动态add进去就可以。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for (int i = 0; i < n; i++) {
            nums1[m + i] = nums2[i];
        }
        Arrays.sort(nums1);
    }
}

这里有取巧的成分了,因为直接使用了Arrays.sort方法。感觉不是出题人的意图。

方法二

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int p1 = 0;
        int p2 = 0;
        int[] result = new int[m + n];
        int current;

        while (p1 < m || p2 < n) {
            //如果nums1已经取完了,那么直接取nums2的
            if (p1 == m) {
                current = nums2[p2];
                p2++;
            } else if (p2 == n) {//如果nums2已经取完了,那么直接取nums1的
                current = nums1[p1];
                p1++;
            } else if (nums1[p1] < nums2[p2]) {//比较两个数的大小,然后进行指针的移动    
                current = nums1[p1];
                p1++;
            } else {
                current = nums2[p2];
                p2++;
            }
            result[p1 + p2 - 1] = current;

        }

        //重新赋值        
        for (int i = 0; i < result.length; i++) {
            nums1[i] = result[i];
        }


    }
}    

复杂度分析

  • 时间复杂度:O(m+n)O(m+n)while中最多遍历m+n,加上form+n,所以最坏的情况下是2(m+n)等于O(m+n)O(m+n)
  • 空间复杂度:O(m+n)O(m+n),申请了一个m+n的数组

方法三:逆向指针

从题目可以知道nums1的空间是足够大的,逆向指针的方法就是要除去方法二的临时数组申请,思路是从nums1nums2 的数组末尾取数,比较其值,大的放nums1末尾,因为nums1的空间大于m+n,最坏的情况下,nums2里面的全部元素 都比nums1大,这样就不会存在覆盖原有nums1数据的问题。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
          int p1 = m - 1;
        int p2 = n - 1;
        int current;


        while (p1 > -1 || p2 > -1) {
            //如果nums1已经取完了,那么直接取nums2的
            if (p1 == -1) {
                current = nums2[p2];
                p2--;
            } else if (p2 == -1) { //如果nums2已经取完了,那么直接取nums1的
                current = nums1[p1];
                p1--;
            } else if (nums1[p1] < nums2[p2]) {//比较两个数的大小,然后进行指针的移动
                current = nums2[p2];
                p2--;
            } else {
                current = nums1[p1];
                p1--;
            }
            nums1[p1 + p2 + 2] = current;
        }


    }
}

复杂度分析

  • 时间复杂度:O(m+n)O(m+n),最多遍历m+n
  • 空间复杂度:O(1)O(1),原地排序,常数额外空间