Median of Two Sorted Arrays(求中位数)

题目链接
题目大意:从俩个排序好的数组里找到这两个数组的中位数,时间复杂度为 O(log (m+n)),m,n为两数组长度

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5
这里写图片描述
这里写图片描述
为什么i是在小的数组里呢?因为如果i是在大的数组里的话,那么算出来的j可能会是负数。

博主刚学c++代码写得很差

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> A = nums1;
        vector<int> B = nums2;
        // 交换数组,A为长度小的数组,B为长度大的数组
        if(A.size() > B.size()){
            vector<int> t = B;
            B = A;
            A = t;
        }

        int n = A.size(), m = B.size();
        if(n==0){
            if(m%2==1){
                return (double)B[(m-1)/2];
            }else{
                return (double)(B[(m-1)/2] + B[(m-1)/2+1])/2.0;
            }
        }
        int iMin = 0;
        int iMax = n;
        double LMAX = 0, RMIN = 0;
        // 二分查找i
        while(iMin <= iMax){
            int i = iMin + (iMax-iMin)/2;
            int j = (m+n+1)/2-i;
            // 存在临界情况即一整个数组在一边
            if((i==n || j==0 || A[i]>=B[j-1])
            && (j==m || i==0 || B[j]>=A[i-1])){
                if(i==0){
                    LMAX = B[j-1];
                }else if(j==0){
                    LMAX = A[i-1];
                }else{
                    LMAX = max(A[i-1], B[j-1]);
                }

                if(i==n){
                    RMIN = B[j];
                }else if(j==m){
                    RMIN = A[i];
                }else{
                    RMIN = min(A[i], B[j]);
                }
                break;
            }else if(i>0 && A[i-1] > B[j]){
                iMax = i-1;
            }else if(j>0 && B[j-1] > A[i]){
                iMin = i+1;
            }
        }
        if((n+m)%2==0){
            return (double)(LMAX+RMIN)/2.0 ;
        }else{
            return LMAX;
        }
    }
};

二进制问题half = (iMin+iMax)/2 == iMin + (iMax-iMin)/2 == iMin&iMax + (iMin^iMax)>>1;
可以理解过iMax和iMin的和为n, n的一半等于 a + (b-a)/2 (a+b==n, && a<=b)
举个例子a+b=9, 4 == 9/2 == 2+(7-2)/2 == 1+(8-1)/2 == 3+(6-3)/2
iMin&&iMax + (iMin^iMax)>>1 的原理差不多就是这样。
一份23ms的优秀提交(别人的)

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        if (m > n) return findMedianSortedArrays(nums2, nums1);
        int i, j, imin = 0, imax = m, half = (m + n + 1) / 2;
        while (imin <= imax) {
            i = (imin & imax) + ((imin ^ imax) >> 1);
            j = half - i;
            if (i > 0 && j < n && nums1[i - 1] > nums2[j]) imax = i - 1;
            else if (j > 0 && i < m && nums2[j - 1] > nums1[i]) imin = i + 1;
            else break;
        }
        int num1;
        if (!i) num1 = nums2[j - 1];
        else if (!j) num1 = nums1[i - 1]; 
        else num1 = max(nums1[i - 1], nums2[j - 1]);
        if ((m + n) & 1) return num1;
        int num2;
        if (i == m) num2 = nums2[j];
        else if (j == n) num2 = nums1[i];
        else num2 = min(nums1[i], nums2[j]);
        return (num1 + num2) / 2.0;
    }
};

// 加上这个可以提高io速度

static const auto _____ = []()
{
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        return nullptr;
 }();

猜你喜欢

转载自blog.csdn.net/weixin_39778570/article/details/80744363