寻找两个有序数组的中位数

寻找两个有序数组的中位数

1. 题目描述:

​ 给定两个大小为 m 和 n 的有序数组 ,nums1nums2,请你找出这两个有序数组的中位数,,并且要求算法的时间复杂度为 O(log(m + n))。你可以假设这两个数组nums1nums2不同时为空。

示例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 = 4len2 = 2 。为了便于题目分析,我们将每一个数组的空隙都填上#号,就变成了nums1 = [# 1 # 2 # 3 # 7 #]nums2 = [# 4 # 6 #],长度分别变成了2 * len1 + 1 = 92 * 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)012345678
元素#1#2#3#7#
刀的位置L1c1R1

L2 = nums2[(c2 - 1) / 2]

R2 = nums2[c2 / 2]

位置(nums2)012345678
元素#4#6#
刀的位置L2c2R2

​ 中位数 = [ 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)012345678
元素#1#2#3#7#
刀的位置L1、c1、R1

L2 = nums2[(c2 - 1) / 2]

R2 = nums2[c2 / 2]

位置(nums2)012345678
元素#4#6#
刀的位置L2、c2、R2

上面L2 = 4 > R1 = 3,所以c1 继续右移,c2左移

L1 = nums1[(c1 - 1) / 2]

R1 = nums1[c1 / 2]

位置(nums1)012345678
元素#1#2#3#7#
刀的位置L1c1R1

L2 = nums2[(c2 - 1) / 2]

R2 = nums2[c2 / 2]

位置(nums2)012345678
元素#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;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值