Leetcode刷题经验

Leetcode刷题经验

热题HOT100

4、寻找两个正序数组的中位数

由于题目中要求时间复杂度需要降低到 O(log(m+n)),故可以采用二分查找,另外,根据中位数的定义,当两个正序数组的总长度m+n为奇数时,则其对应的中位数是两个有序数组中下标为 (m+n)/2的元素,当 m+n为偶数时,中位数是两个有序数组中下标为 (m+n)/2的元素以及下标为(m+n)/2+1元素的平均值。
解题思路:

假设两个有序数组分别是A 和B。要找到第 k个元素,我们可以比较 A [ k / 2 − 1 ] A[k/2−1] A[k/21] B [ k / 2 − 1 ] B[k/2−1] B[k/21] ,其中 / 表示整数除法。由于 A [ k / 2 − 1 ] A[k/2−1] A[k/21] B [ k / 2 − 1 ] B[k/2−1] B[k/21]的前面分别有 A [ 0.. k / 2 − 2 ] A[0..k/2−2] A[0..k/22] B [ 0.. k / 2 − 2 ] B[0..k/2−2] B[0..k/22],即 k/2−1 个元素,对于 A [ k / 2 − 1 ] A[k/2−1] A[k/21] B [ k / 2 − 1 ] B[k/2−1] B[k/21] 中的较小值,最多只会有 k − 2 k−2 k2个元素比它小,而且它本身也不可能是第 k k k小元素,故可以将 A [ 0.. k / 2 − 1 ] A[0..k/2−1] A[0..k/21]这些元素全部删除即可。
因此,可归纳得出三种情况:
第一种情况:
如果 A [ k / 2 − 1 ] < B [ k / 2 − 1 ] A[k/2−1]<B[k/2−1] A[k/21]<B[k/21],则比 A [ k / 2 − 1 ] A[k/2−1] A[k/21] 小的数最多只有A的前 k / 2 − 1 k/2-1 k/21个数和B的前 k / 2 − 1 k/2-1 k/21个数,即比 A [ k / 2 − 1 ] A[k/2−1] A[k/21] 小的数最多只有 k − 2 k-2 k2个,因此 A [ k / 2 − 1 ] A[k/2−1] A[k/21]不可能是第 k k k个数,那么从 A [ 0 ] A[0] A[0] A [ k / 2 − 1 ] A[k/2−1] A[k/21] 也都不可能是第 k k k个数,故可以全部排除。
第二种情况:
如果 A [ k / 2 − 1 ] > B [ k / 2 − 1 ] A[k/2−1]>B[k/2−1] A[k/21]>B[k/21],则同理可以排除 B [ 0 ] B[0] B[0] B [ k / 2 − 1 ] B[k/2−1] B[k/21]
第三种情况:
如果 A [ k / 2 − 1 ] = B [ k / 2 − 1 ] A[k/2−1]=B[k/2−1] A[k/21]=B[k/21],则归入第一种情况处理即可。
此外,还需要注意以下三种特殊情况:
1、 如果 A [ k / 2 − 1 ] A[k/2−1] A[k/21] 或者 B [ k / 2 − 1 ] B[k/2−1] B[k/21]越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 k k k的值,而不能直接将 k k k减去 k / 2 k/2 k/2
2、 如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 k k k 小的元素。
3、 如果 k = 1 k=1 k=1,我们只要返回两个数组首元素的最小值即可。

由于每经历一轮循环就可以将查找范围减少一半,因此时间复杂度是 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n)),而对应的空间复杂度为 O ( 1 ) O(1) O(1)

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length1=nums1.length,length2=nums2.length;
        int totalLength=length1+length2;
        if(totalLength%2==1){
            int midIndex=totalLength/2;
            double median=getKthElement(nums1,nums2,midIndex + 1);
            return median;
        }else{
            int midIndex1=totalLength/2-1,midIndex2=totalLength/2;
            double median=(getKthElement(nums1,nums2,midIndex1 + 1)+getKthElement(nums1, nums2, midIndex2 + 1)/2);
            return median;
        }

    }
    public double getKthElement(int[] nums1, int[] nums2,int k) {
        int length1=nums1.length,length2=nums2.length;
        int index1=0,index2=0;
        while(true){
            if(index1==length1){return nums2[index2 + k -1];}
            if(index2==length2){return nums1[index1 + k -1];}
            if(k==1){return Math.min(nums1[index1],nums2[index2]);}
            int half=k/2;
            int newIndex1=Math.min(index1+half,length1)-1;
            int newIndex2=Math.min(index2+half,length2)-1;
            int point1=nums1[newIndex1],point2=nums2[newIndex1];
            if(point1<=point2){
                k-=(newIndex1-index1+1);
                index1=newIndex1+1;
            }else{
                 k-=(newIndex2-index2+1);
                index2=newIndex2+1;
            }
        }
    }
}

不过,该问题还有更好的解决办法,等弄懂了后期再进行更新!
欢迎大家交流,一起进步!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值