题目:
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
解题思路:
详细的题解请参见https://leetcode.cn/problems/median-of-two-sorted-arrays/solutions/2950686/tu-jie-xun-xu-jian-jin-cong-shuang-zhi-z-p2gd
下面是我对题解的一些理解,我使用的是闭区间的写法:
这道题的难点就在于时间复杂度要求,就限制了不能用遍历来找到中位数。
中位数也就是有序数组中排在中间位置的数,换句话说中位数把有序数组分成了两部分,两部分的元素个数相同(如果数组元素个数是奇数,则让左边部分比右边部分多一个),并且左边部分的所有元素都比右边部分的所有元素小(即是左边部分的最大值都小于右边部分的最小值)。
既然我们知道了m和n,自然也就知道了左边部分和右边部分的元素个数(m + n + 1)/ 2,那么假设左边部分中的元素是由nums1中的i个元素+nums2中的j个元素组成,且i + j == (m + n + 1)/ 2,所以我们如果知道了i,自然也就知道了j,也就得到了左边部分的元素和右边部分的元素,也就是一种划分情况,枚举i的个数,也就得到不同的左右部分划分情况,其中只有一个划分情况能够满足左边部分的最大值小于右边部分的最小值,此时也就找到了中位数,如果数组元素个数是奇数,中位数=左边部分的最大值,如果是偶数,则中位数=(左边部分最大值 + 右边部分最小值)/ 2。
满足条件的划分是唯一的,并且此时的 i 是满足nums1[i] <= nums2[j + 1]的最大值,而这个i我们可以通过二分的方法来查找。
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {// 1、如果nums1的长度大于nums2,则交换if(nums1.length > nums2.length){int[] temp = nums1;nums1 = nums2;nums2 = temp;}// 2、二分寻找最大满足nums1[i] < nums2[j + 1]int m = nums1.length, n = nums2.length;int left = 0, right = m - 1;while(left <= right){int i = left + (right - left) / 2;int j = (m + n + 1) / 2 - (i + 1) - 1;if(nums1[i] < nums2[j + 1]){left = i + 1;}else{right = i - 1;}}int i = right;int j = (m + n + 1) / 2 - (i + 1) - 1;int ai = i >= 0 ? nums1[i] : Integer.MIN_VALUE;int bj = j >= 0 ? nums2[j] : Integer.MIN_VALUE;int ai1 = (i + 1) < m ? nums1[i + 1] : Integer.MAX_VALUE;int bj1 = (j + 1) < n ? nums2[j + 1] : Integer.MAX_VALUE;int max1 = Math.max(ai, bj);int min2 = Math.min(ai1, bj1);return (m + n) % 2 > 0 ? max1 : (max1 + min2) / 2.0;}
}