当前位置 博文首页 > Ocean曈的博客:在两个长度相等的排序数组中找到上中位数

    Ocean曈的博客:在两个长度相等的排序数组中找到上中位数

    作者:[db:作者] 时间:2021-06-21 12:39

    题目地址:
    https://www.nowcoder.com/practice/6fbe70f3a51d44fa9395cfc49694404f?tab=answerKey

    题目描述
    给定两个有序数组arr1和arr2,已知两个数组的长度都为N,求两个数组中所有数的上中位数。
    上中位数:假设递增序列长度为n,若n为奇数,则上中位数为第n/2+1个数;否则为第n/2个数
    [要求]
    时间复杂度为O(logN),额外空间复杂度为O(1)O(1)

    这题简单点的思路,其实就是一个双指针,
    1.index1,指向数组arr1,index2指向数组arr2,
    2.arr1[index1]>arr2[index2],index2++,否则 index1++
    3.然后直到index1+index2 等于数组的长度,输出最后移动的指针指向的数字即可

    代码实现如下:

    public int findMedianinTwoSortedAray(int[] arr1, int[] arr2) {
            int index1 = 0;
            int index2 = 0;
            int length = arr1.length;
            while (index1+index2<length-1){
                if (arr1[index1]<arr2[index2]){
                    index1++;
                }else {
                    index2++;
                }
            }
            return Math.min(arr1[index1],arr2[index2]);
       }
    

    但是这个算法的时间复杂度达到了O(n),不符合题目要求。所以,基本上,一般看到要求时间复杂度为O(logN),基本上能做的就是二分法了,

    1.取两个数组的中间位置,mid1,mid2

    2.如果 arr1[mid1] == arr2[mid2],则得到结果 返回arr1[mid1]即可,

    3.arr1[mid1]>arr2[mid2],
    数组arr1中mid1位置以后的数都不可能是整体的上中位数,数组arr2中mid2位置以前的数都不可能是整体的上中位数。所以现在只需要考虑arr1[left1…mid1]、arr2[mid2…right],这两部分的元素个数相同,它们的上中位数就是整体的上中位数。

    然后分一下数组长度的奇偶情况,

    3.1同样arr1[mid1]>arr2[mid2],
    如果当前数组长度是偶数,只需要 留下 arr1 :[left1,mid1] arr2(mid2,right2]
    如果当前数组长度是奇数,只需要 留下 arr1 :[left1,mid1] arr2[mid2,right2]
    在这种情况下,可以看到 arr2 的右边因为数组长度分奇偶,而导致了开合。这样做是为了保证arr1 剩余长度等于 arr2 剩余长度。

    4.如果arr1[mid1]<arr2[mid2]
    如果当前数组长度是偶数,只需要 留下 arr1 :(mid1,right1] arr2[left2,mid2]
    如果当前数组长度是奇数,只需要 留下 arr1 :[left1,mid1] arr2[mid2,right2]

    示意图如下
    在这里插入图片描述

    实现代码如下:

     public int findMedianinTwoSortedAray(int[] arr1, int[] arr2) {
    
            return find(arr1,0,arr1.length,arr2,0,arr2.length);
        }
    
        int find(int[] arr1, int left1, int rigth1, int[] arr2, int left2, int rigth2) {
            int mid1 = (rigth1 - left1-1) / 2 + left1;
            int mid2 = (rigth2 - left2-1) / 2 + left2;
    
            if (arr1[mid1]==arr2[mid2]){
                return arr1[mid1];
            }
            if (rigth1 - left1 == 1){
                return Math.min(arr1[left1],arr2[left2]);
            }
    
            if ((rigth1-left1)%2==1){
                if (arr1[mid1]>arr2[mid2]){
                    return find(arr1,left1,mid1+1,arr2,mid2,rigth2);
                }else {
                    return find(arr1,mid1,rigth1,arr2,left2,mid2+1);
                }
            }else {
                if (arr1[mid1]>arr2[mid2]){
                    return find(arr1,left1,mid1+1,arr2,mid2+1,rigth2);
                }else {
                    return find(arr1,mid1+1,rigth1,arr2,left2,mid2+1);
                }
            }
    
        }
    

    重点推理,就是每次二分之后剩余的数组的中上位数,为全部数组的中上位数。大家可以用画图的方案,来推理一下。
    然后要分一下奇数偶数中间位保留跟丢弃的情况。