(二分 难题)Leetcode 4. 寻找两个有序数组的中位数

https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

给定两个大小为 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

题意为:
要求两个有序数组的中位数,且时间复杂度要求在O(log(m+n))内。

思路
由于时间复杂度的原因,我们不难想到要用二分;
我们假设两个数组分别s1,s2,长度分别为n,m,将连个数组都切成两半,分别有s1左,s1右,s2左,s2右表示;
用Lmax1表示s1左的最大值,Lmin1表示s1右的最小值,Lmax2表示s2左的最小值,Lmin2表示s2右的最小值;
判断是否是中位数的根据为:

(1)Lmin1<=Lmax2 && Lmin2<=Lmax1
(2)i+j=m+n-i-j

根据中位数的性质,len(s1左)+len(s2左)==len(s1右)+len(s2右);
所以假设在s1中切得位置下标为i,那么在s2中切的下表对应为j=((n+m)/2-i);
至此可以针对s1数组做二分,有了s1的下标,s2的下表也对应可以求出;
这里再加入一个tricks,因为奇偶的关系,我们将数组插入#,那么s1,s2的长度变为2n+1,2m+1;求原坐标就是除以2即可;

判断是否为中位数的条件变为:
限制条件如下:

Lmax1= i==0? INT_MIN:s1[(i-1)/2]
Lmin1= i==2n? INT_MAX:s1[i/2]
Lmax2= j==0? INT_MIN:s2[(j-1)/2]
Lmin2= j==2n? INT_MAX:s2[j/2]

总体来说有一些难度,主要是限定条件分清楚。
代码如下:

class Solution {
public:
    double binary_find(vector<int>& nums1,vector<int>& nums2)
    {
        int len1=nums1.size(),len2=nums2.size();
        if(len1>len2)
        {
            return binary_find(nums2,nums1);
        }
        int Lmin1,Lmax1,Lmin2,Lmax2,lo=0,hi=2*len1;
        int i,j;
        while(lo<=hi)
        {
            i=(lo+hi)/2;
            j=len1+len2-i;

            Lmax1=i==0?INT_MIN:nums1[int((i-1)/2)];
            Lmin1=i==2*len1?INT_MAX:nums1[int(i/2)];
            Lmax2=j==0?INT_MIN:nums2[int((j-1)/2)];
            Lmin2=j==2*len2?INT_MAX:nums2[int(j/2)];

            if(Lmax1<=Lmin2&&Lmax2<=Lmin1)
                break;
            else if(Lmax1>Lmax2)
                hi=i-1;
            else if(Lmax2>Lmin1)
                lo=i+1;

        }
        return (max(Lmax1,Lmax2)+min(Lmin1,Lmin2))/2.0;
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        return binary_find(nums1,nums2);
    }
};
发布了741 篇原创文章 · 获赞 185 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/Fire_to_cheat_/article/details/103388866
今日推荐