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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        /* 寻找中位数,可以看成寻找一条分割线,使分割线两侧,左边小于右边
         * 当数组长度为奇数时,我们让左边元素多一个,则此时,中位数为左边两个最大数的最大值
         * 当数组长度为偶数时,中位数为左边最大值和右边最小值的平均数
         */

        // 为了使第二个数组右边总是有值,当nums1长度大于nums2长度时,我们交换两个引用
        if(nums1.length > nums2.length) {
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
        }
        // 左边所有元素需要满足的个数
        int totalLeft = (nums1.length + nums2.length + 1) / 2; 
        // 分割线寻找的左右边界
        int left = 0, right = nums1.length; 
        while(left < right) {
            // 取左右边界平均(二分)作为i,则第二个数组左边元素个数为j
            // 加1为了两个元素时不进入死循环
            int i = (left + right + 1) / 2, j = totalLeft - i;
            // 数组1左边最大值的数值大于数组2右边最小值,此时分割线需要左移
            if (nums1[i - 1] > nums2[j]) {
                right = i - 1;
            } else {
                // 反面
                left = i;
            }
        }
        // 重新定义分割线
        int i = left, j = totalLeft - i;
        // 分别得到nums1 nums2左边最大值和右边最小值(需要考虑边界情况)
        int nums1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];
        int nums1RightMin = i == nums1.length ? Integer.MAX_VALUE : nums1[i];
        int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];
        int nums2RightMin = j == nums2.length ? Integer.MAX_VALUE : nums2[j];
        // 数组长度为奇数,返回左边最大值,偶数返回左边最大值和右边最小值的平均数
        if ((nums1.length + nums2.length) % 2 == 1) {
            return Math.max(nums1LeftMax, nums2LeftMax);
        } else {
            return (double)(Math.max(nums1LeftMax, nums2LeftMax) + Math.min(nums1RightMin, nums2RightMin)) / 2;
        }
    }
}