给定两个大小为 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
思路:
1.就是用外排法给两个有序数组排序,然后找出中位数,但是时间复杂度O(m+n),不满足题目要求
2.YouTube帮助理解的视频
这个外国小哥讲的很好,很清楚
大致思路是
将两个数组都分成两个部分
x1 x2 x3 x4 | x5 x6 x7
y1 y2 y3 | y4 y5 y6 y7
使得 左部分的元素数 和 右部分的元素数最多相差1
然后满足x4 <= y4 && y3 <= x5
其实这样就是把数画成了两堆,左堆的数全部<=右堆的数
那么
中位数就是(Max(x4,y3)+Min(x5,y4))/2
时间复杂度就是用来找这个划界的点O(log(min(m,n))),就是用二分查找,对长度最小的一个数组进行划界,那另外一个的界就可以算出来了

class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if(nums1.length > nums2.length){
int[] tmp = nums1;
nums1 = nums2;
nums2 = tmp;
}
int len1 = nums1.length;
int len2 = nums2.length;
int low = 0;
int high = len1;
while(low <= high){
int partx = high + (low - high>>1);
int party = ((len1+len2+1)>>1)-partx;
int leftx = partx == 0?Integer.MIN_VALUE:nums1[partx-1];
int lefty = party == 0?Integer.MIN_VALUE:nums2[party-1];
int rightx = partx == len1?Integer.MAX_VALUE:nums1[partx];
int righty = party == len2?Integer.MAX_VALUE:nums2[party];
if(leftx <= righty && lefty <= rightx){
if((len1+len2)%2 == 0){
//偶数情况下
return (double)(Math.max(leftx,lefty) + Math.min(rightx,righty))/2;
}else
//奇数情况下
return (double)(Math.max(leftx,lefty));
}else if(leftx > righty){
high = partx - 1;
}else if(lefty > rightx){
low = partx + 1;
}
}
return -1;
}
}
位运算太容易出错了,be careful
本文介绍了一种求解两个有序数组中位数的高效算法,时间复杂度为O(log(min(m,n)))。通过将数组分为左右两部分,确保左部分元素小于等于右部分,找到划分点即可计算中位数。
655

被折叠的 条评论
为什么被折叠?



