题目:
Median of Two Sorted Arrays寻找两个正序数组的中位数。
给定两个大小为 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
解题分析:
很显然,这个题直接用暴力破解的话,时间复杂度为:O(m+n),空间复杂度为:O(m+n);
这个题的核心是:
一,要明白什么是中位数,以及它与偶数even个数和奇数odd个数的关系;
二是,由于是排好序的数组,很显然这个题采用的方法是:二分查找;
二分查找的核心是:【1】partitioni + partitioni = (m + n + 1)/2;对数组 A 的做 partition 的位置是区间
[0,m];
并且,【2】partition后,maxLeftA <= minRightB && maxLeftB <= minRightA,
满足这两个条件的话,中位数median就在这四个数(maxLeftA,minRightB,maxLeftB,minRightA)中,
如果m+n是奇数(总个数为奇数个):
median = max(maxLeftA, maxLeftB)
如果m+n是偶数(总个数为偶数个):
median = (max(maxLeftA, maxLeftB) + min(minRightA, minRightB)) / 2
这个题,虽然是个hard难度的题,但如果明白原理的话,还是很简单的;
本篇解题分析只列举了核心要点,具体讲解可以看一位印度朋友的讲解视频,个人感觉讲的非常好,通俗易懂,只要你肯静下心来花上不到半小时耐心听完!
YouTube原视频地址:https://www.youtube.com/watch?v=LPFhl65R7ww
国内B站搬运视频:https://www.bilibili.com/video/BV1Y4411G7YG?from=search&seid=10863350334241030260
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if(nums1.length > nums2.length){
return findMedianSortedArrays(nums2, nums1);
}
int m = nums1.length;
int n = nums2.length;
int lo = 0;
int hi = m;
while(lo <= hi){
// paartition i, j 要满足: i + j = (m + n + 1)/2
// int i = lo + (hi - lo)/2;
// int j = (m + n + 1)/2 - i;
// 阿三哥关于partitioni和partitionj的写法:
int i = (lo + hi)/2;
int j = (m + n + 1)/2 - i;
int maxLeftA = i == 0 ? Integer.MIN_VALUE : nums1[i - 1];
int minRightA = i == m ? Integer.MAX_VALUE : nums1[i];
int maxLeftB = j == 0 ? Integer.MIN_VALUE : nums2[j - 1];
int minRightB = j == n ? Integer.MAX_VALUE : nums2[j];
// 核心:
if(maxLeftA <= minRightB && maxLeftB <= minRightA){
// 如果总长度为偶数
if((m + n)%2 == 0){
return (double)(Math.max(maxLeftA, maxLeftB) + Math.min(minRightA, minRightB)) / 2;
}else{
// 如果总长度为奇数
return (double) Math.max(maxLeftA, maxLeftB);
}
}else if(maxLeftA > minRightB){
hi = i - 1;
}else{
// 也就是 maxLeftB > minRightA
lo = i + 1;
}
}
return 0.0;
}
}