寻找两个有序数组的中位数
1. 题目描述:
给定两个大小为 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
2. 题目分析:
假如nums1 = [1, 2, 3, 7]
,nums2 = [4, 6]
,长度分别为len1 = 4
和len2 = 2
。为了便于题目分析,我们将每一个数组的空隙都填上#号,就变成了nums1 = [# 1 # 2 # 3 # 7 #]
, nums2 = [# 4 # 6 #]
,长度分别变成了2 * len1 + 1 = 9
和2 * len2 + 1 = 5
。
用刀c1
将数组nums1
切成两半,刚开始c1
的位置就是2 * len1 / 2 = 4
,同样用刀
c2将数组
nums2切成两半,刚开始
c2的位置就是len1 + len2 - c1 = 2
注意:下面算L1、R1、L2、R2的时候,nums1和nums2里面是没有#号的,nums1=[1, 2, 3, 7]
#号的好处就是可以让我们算L1,R1这些时,抛掉很多顾忌,又能精确地用刀将左右分隔开
L1 = nums1[(c1 - 1) / 2]= nums1[1] = 2
;
R1 = nums1[c1 / 2] = nums1[2] = 3
;
位置(nums1) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 1 | # | 2 | # | 3 | # | 7 | # |
刀的位置 | L1 | c1 | R1 |
L2 = nums2[(c2 - 1) / 2]
;
R2 = nums2[c2 / 2]
;
位置(nums2) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 4 | # | 6 | # | ||||
刀的位置 | L2 | c2 | R2 |
中位数 = [ max (c1的左边和c2的左边) + min(c1的最右边和c2的右边) ] / 2
这就要求L2 不能大于 R1,L1 不能大于 R2,上图中L2 = 4 > R1 = 3,为了保持两边总体数量均衡,那么刀c1的位置应该要右移,c2的位置应该左移,就变成:
L1 = nums1[(c1 - 1) / 2]
;
R1 = nums1[c1 / 2]
;
位置(nums1) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 1 | # | 2 | # | 3 | # | 7 | # |
刀的位置 | L1、c1、R1 |
L2 = nums2[(c2 - 1) / 2]
;
R2 = nums2[c2 / 2]
;
位置(nums2) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 4 | # | 6 | # | ||||
刀的位置 | L2、c2、R2 |
上面L2 = 4 > R1 = 3,所以c1 继续右移,c2左移
L1 = nums1[(c1 - 1) / 2]
;
R1 = nums1[c1 / 2]
;
位置(nums1) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 1 | # | 2 | # | 3 | # | 7 | # |
刀的位置 | L1 | c1 | R1 |
L2 = nums2[(c2 - 1) / 2]
;
R2 = nums2[c2 / 2]
;
位置(nums2) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|---|
元素 | # | 4 | # | 6 | # | ||||
刀的位置 | c2 |
c2 = 0,已经到了边界,则令L2 = MIN_VALUE,这样L2 > R1就不会成立
java代码:
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2)
{
int L1 = 0, R1 = 0;
int L2 = 0, R2 = 0;
int len1 = nums1.length;
int len2 = nums2.length;
int low = 0, high = 2 * len1;
while(low <= high)
{
int c1, c2;
c1 = (low + high) / 2;
c2 = len1 + len2 - c1;
L1 = c1 == 0 ? Integer.MIN_VALUE : nums1[(c1 - 1) / 2];
R1 = c1 == 2 * len1 ? Integer.MAX_VALUE : nums1[c1 / 2];
L2 = c2 == 0 ? Integer.MIN_VALUE : nums2[(c2 - 1) / 2];
R2 = c2 == 2 * len2 ? Integer.MAX_VALUE : nums2[c2 / 2];
if(L1 > R2)
{
high--;
}
else if(L2 > R1)
{
low++;
}
else
{
break;
}
}
double ret;
return ret = ( Math.max(L1, L2) + Math.min(R1, R2) ) / 2.0;
}
}