剑指Offer数组习题-合并两个有序数组

剑指Offer数组习题-合并两个有序数组

题目描述

有两个排序的数组A1和A2,内存在A1的末尾有足够多的空余空间容纳A2。请实现一个函数,把A2中所有的数字插入到A1中并且所有的数字是排序的。

题目题解(Java)

    /**
     * @param a1:需要容纳A1+A2的数组
     * @param lengthA1:A1的实际长度
     * @param a2:需要被合并的数组
     */
    private static void sortTwoArray(int[] a1, int lengthA1, int[] a2) {
        // 异常流程:当A1为空或者A2为空或者A2的长度为0的时候,不进行计算
        if (a1 == null || a2 == null || a2.length == 0) {
            return;
        }

        //异常流程:当A1的长度不满足于同时容纳A1+A2的数字,不进行计算
        if (a1.length < lengthA1 + a2.length) {
            return;
        }

        //正常流程
        int lengthA2 = a2.length;
        int p = lengthA1 + lengthA2 - 1; //指向A1+A2长度内的最后一个可用坐标

        int i = lengthA1 - 1; //指向A1的最后一个坐标
        int j = lengthA2 - 1; //指向A2的最后一个坐标

        while (i >= 0 && j >= 0) {
            if (a1[i] >= a2[j]) {
                a1[p] = a1[i];
                i--;
            } else {
                a1[p] = a2[j];
                j--;
            }
            p--;
        }

        //A2有剩余
        while (j >= 0) {
            a1[p] = a2[j];
            p--;
            j--;
        }

        //A1有剩余,保留在原位置
    }

**感悟:**这道题,其实网上也有很多的同学给出了解答,但是看了几篇发现,大家往往都忽略了异常处理流程,看了几天的剑指offer,其实感触最深的就是里面的异常处理,都是放在最前面,所以还希望大家多多重视异常流程。

算法详解:

  • 异常处理流程:当A1为空或者A2为空或者A2的长度为0的时候,不进行计算
  • 异常处理流程:当A1的长度不满足于同时容纳A1+A2的数字,不进行计算
  • 正常处理流程:
    我们采用的是时间复杂度为O(n)的算法,从后往前复制,减少移动的次数。
    变量含义阐述:
    • p代表的是A1+A2长度内的最后一个可用坐标
    • i 代表A1的没有被复制的最后一个坐标
    • j 代表A2的没有被复制的最后一个坐标

具体的算法步骤:
从A1和A2的最后一位开始比较:

如果A1[i] >= A2[j], A1[p] = A1[i], 复制之后,i向前移动一位,p向前移动一位;
如果 A1[i] < A2[j], A1[p] = A2[j],复制之后,j向前移动一位,p向前移动一位;
一直到A1或者A2有一个全部复制结束为止。

当然在跳出循环之后,我们还要考虑到,A1或A2还有剩余的怎么办?

  • A1有剩余,由于数组有序,那么剩余的必然是小于已经复制的那些数字,所以A1剩余的话,就保持不动就可以了。
  • A2 有剩余n位元素,那么A1的前n位必然是已经被复制完毕,这个时候我们只需要按顺序,通过循环将A2剩余的元素,放置在A1的前n位即可。

猜你喜欢

转载自blog.csdn.net/Android_Glimmer/article/details/89708107