//给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。//// 进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?//////// 示例 1://// 输入:nums1 = [1,3], nums2 = [2]//输出:2.00000//解释:合并数组 = [1,2,3] ,中位数 2////// 示例 2://// 输入:nums1 = [1,2], nums2 = [3,4]//输出:2.50000//解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5////// 示例 3://// 输入:nums1 = [0,0], nums2 = [0,0]//输出:0.00000////// 示例 4://// 输入:nums1 = [], nums2 = [1]//输出:1.00000////// 示例 5://// 输入:nums1 = [2], nums2 = []//输出:2.00000////////// 提示:////// nums1.length == m// nums2.length == n// 0 <= m <= 1000// 0 <= n <= 1000// 1 <= m + n <= 2000// -106 <= nums1[i], nums2[i] <= 106//// Related Topics 数组 二分查找 分治算法// 👍 3718 👎 0
查找中位数,而且特意提醒了O(log (m+n))复杂度。
有到log到情况一般都是要二分的,因此这题是对两个数组进行二分。
这题写起来还是挺烦的,我本来就对边界值不敏感,对着别人对题解都把边界值写错。
大体思路就是,因为整体数组长度是知道的,就是m+n。
因此对nums1进行二分对时候也变相在对nums2进行二分,假设nums1划分到a位置,nums2也就相应到划分到(m+n)/2 - a。
因此保证划分的分割线左边的数小于右边即可。
class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int m = nums1.length;int n = nums2.length;if (m > n) {return findMedianSortedArrays(nums2, nums1);}int left = 0;int right = m;// 分割线左边的总数字,+1是为了保证如果奇数的话,left划到左边多一个int totalLeft = (m + n + 1) / 2;while (left < right) {// 划好分割线int i = (left + right + 1) / 2;int j = totalLeft - i;// 保证分割线左边的要小于右边if (nums1[i - 1] > nums2[j]) {// 分割线左边大于右边说明划的偏右了,要向左right = i - 1;}else {left = i;}}int i = left;int j = totalLeft - i;int n1LeftMax = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];int n1RightMin = i == m ? Integer.MAX_VALUE : nums1[i];int n2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];int n2RightMin = j == n ? Integer.MAX_VALUE : nums2[j];// 因为保证了如果奇数的话,left划到左边多一个,所以如果奇数直接返回左边最大的if ((m + n) % 2 == 1) {return Math.max(n1LeftMax, n2LeftMax);}// 否则返回中位数左右的中位数return (double) (Math.max(n1LeftMax, n2LeftMax) + Math.min(n1RightMin, n2RightMin)) / 2;}}
