两个排序数组的中位数-规律加二分法

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。

请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n))。

示例 1:

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

中位数是 2.0

示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

中位数是 (2 + 3)/2 = 2.5


public double FindMedianSortedArrays(int[] nums1, int[] nums2) {
    int m = nums1.Length;
    int n = nums2.Length;
    if(m>n){
        //保证m<=n
        int[] temp = nums1; nums1 = nums2;nums2 = temp;
        int t = m; m = n; n = t;
    }

    int iMin = 0;
    int iMax = m;//只需要在小的一个数组中寻找i
    int halfLen = (m + n + 1) / 2;//根据公式,用来计算j
    while(iMin <= iMax)
    {
        int i = (iMax + iMin) / 2; //2分法
        int j = halfLen - i; //计算出对应的j
        if(i < iMax && nums2[j-1] > nums1[i])
        {
            iMin = i+1; //数组1的i位置的值小了,数组2的j-1应该小于=数组1的i
        }else if(i > iMin && nums1[i-1] > nums2[j])
        {
            iMax = i-1; //数组1的i位置的值大了,数组1的i-1应该小于=数组2的j
        }else
        {
            //这个位置很合适了,求左边的最大值,注意特殊情况
            int maxLeft = 0;
            if(i == 0){
                maxLeft = nums2[j-1];
            }else if(j == 0)
            {
                maxLeft = nums1[i-1];
            }else{
                maxLeft = Math.Max(nums1[i-1],nums2[j-1]);
            }

            //奇数的话,直接返回左边最大,前面计算i和j会保证左边元素多1
            if((m+n)%2 == 1) return maxLeft;

            //计算右边的最小
            int minRight = 0;
            if(i == m)
            {
                minRight = nums2[j];
            }else if(j == n)
            {
                minRight = nums1[i];
            }else
            {
                minRight = Math.Min(nums2[j],nums1[i]);
            }

            return (maxLeft + minRight)/2f;
        }
    }

    return 0.0;
}


在两个有序的数组中找中位数,中位数是什么,就是可以把一段有序数组分成两段,右边那一段比前面那一段都大。那么就可以想,将有序数组1用i分成两半,同样的将有序数组2用j分成两半,数组1的i和i的右边跟数组2的j和j的右边合并,使他们的个数和左边合并的相同或则少一个,同时合成的右边全都比左边的大,那么在相同个数的情况下,中位数就=(左边最大+右边最小)/2,在左边个数比较多的情况下,中位数就=左边最大。

所以寻找i和j的时候需要保证两个条件,1.左边比右边的个数相同或则多一个。2.数组2第j位大于数组1第i-1位,数组1第i位大于数组2第j-1位,因为i和j是在右边数组,所以一定得保证比它本身上一个元素大。

如果按照这样子区分后,左边最大不是数组1的i-1就是数组2的j-1,而右边最大不是数组1的i就是数组2的j。

时间复杂度是:O(log(min(n,m)))


首页 我的博客
粤ICP备17103704号