LeetCode刷题笔记-4. 寻找两个有序数组的中位数

题目:
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
题解:

class Solution {
    public double findMedianSortedArrays(int[] A, int[] B) {
        int m=  A.length;
        int n= B.length;
        
        if(m>n){//使n大于m
            int[] temp=A;
            A=B;
            B=temp;
            int temp2=m;
            m=n;
            n=temp2;
        }
        int left=0,right=m,mid=(m+n+1)/2;
        while(left<=right){
            int i=(left+right)/2;
            int j=mid-i;
            if(i<right && B[j-1] > A[i]){//i<right是为了保证i不会越界
                left=i+1;//此时i需要右移
            }
            else if(i>left&&A[i-1]>B[j]){//i>left也是为了保证i不会越界
                right=i-1;//此时i需要左移
            }
            else{//此时i的值是完美的,需要寻找左右两部分各自的最大值,此时又分为两种情况 ij在边界或者ij在数组中间位置
                int maxLeft=0;//左半部分最大值
                if(i==0){//i在左边界情况
                    maxLeft=B[j-1];
                }
                else if(j==0){//j在左边界
                    maxLeft=A[i-1];
                }
                else{//ij在界中
                    maxLeft=Math.max(A[i-1],B[j-1]);
                }
                if((m+n)%2==1){//如果为奇数则直接返回左半部分最大值,节省运算时间
                    return maxLeft;
                }
                int  minRight=0;//右半部分最大值
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }
                return (maxLeft+minRight)/2.0;//m+n为偶数则 左半部分最大值和右半部分最大值的平均值为最终结果
            }
        }
        return 0.0;//寻找失败
    }
}

大致思路
由于我太菜了 所以参考的官方的题解。。。。。。
首先说思路,总体上我们需要使用二分法来将寻找合适的值。
由于要找到中位数,所以需要将AB两个数组都一分为二,分成四个小块,即:
left_part | right_part
A[0], A[1], …, A[i-1] | A[i], A[i+1], …, A[m-1]
B[0], B[1], …, B[j-1] | B[j], B[j+1], …, B[n-1]

因为左半部分的两个小块的元素个数要与右半部分相同,所以得到了i与j的关系:i+j=m−i+n−j(或m+n为奇数时m−i+n−j+1),此时为了简化奇偶数情况,使奇数个时中位数在左半部分,固定使用i+j=m−i+n−j+1,得到j=(m+n+1)/2-i 同时为了确保j不为负数,固定使n>=m(如果m>n的话只需要互相AB调换即可)
综上所以,我们需要做的是:
在 [0,m]中搜索并找到目标对象 i,以使: B[j−1]≤A[i] 且 A[i−1]≤B[j], 其中 j =(m+n+1)/2-i ;把i看成自变量 ,j看成因变量,在对A数组的二分查找中寻找符合条件的值即可。
但是有一种特殊的情况,如果i的值为0或m,j的值为0或n会怎么样?
如果A[i−1],B[j−1],A[i],B[j] 中部分不存在,那么我们只需要检查这两个条件中的一个(或不需要检查)。举个例子,如果 i = 0,那么 A[i−1] 不存在,我们就不需要检查 A[i−1]≤B[j] 是否成立。

最后附上官方题解:
https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-shu-b/

发布了10 篇原创文章 · 获赞 3 · 访问量 2267

猜你喜欢

转载自blog.csdn.net/qq_40397223/article/details/104709584