Leetcode Median of Two Sorted Arrays

Problemn

There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

思路

很不好想的一道题!首先想到的是合并两个排序数组然后再选取其中位数。这样时间复杂度是线性不符合他的要求。如果是log的复杂度应该考虑二分法。这个题的关键就在于如何二分。

我自己实在想不到什么办法,参考一下前人的做法:

http://www.cnblogs.com/yuzhangcmu/p/4138184.html

http://algorithmsandme.in/2014/12/find-kth-smallest-element-in-two-sorted-arrays/

中位数可以泛化为取第k小的元素问题,思路如下:

在两个排序数组A中取前k/2个元素,B中取前k-k/2个元素,比较第k/2、k-k/2个元素大小,A[k/2-1] and B[k-k/2-1],如果A[k/2-1]>B[k-k/2-1], 我们假设在B的k-k/2-1位之后找到一个元素B[x]和A[k/2-1]相等,如果合并A[0] ~ A[k/2-1]和B[0] ~ B[x],得到的新数组是前k/2+(x+1)小的元素,这里x>k-k/2-1, k/2+x+1>k。第k个元素一定在这个新数组中,所以我们可以舍弃A中k/2-1之后的部分。同理我们假设在A的k/2-1位之前找到一个元素A[y]和B[k-k/2-1]相等,合并A[0] ~ A[y] and B[0] ~ B[k-k/2-1],得到的新数组长度小于k,第k哥元素一定不在这个新数组中,由此我们可以舍弃B中B[k-k/2-1]与其之前的部分。一图以蔽之:


红色表示我们可以舍弃不考虑的部分,绿色表示第k个元素可能的位置。

现在我们确定k/2个元素或者k-k/2个元素比k小,如果A[k/2-1]>B[k-k/2-1],此时既是上图的情况,红色的部分被扔掉。我们确定的是B中被扔掉的部分都小于我们要求的第k个元素。所以下一步所求是在绿色数组中求第k-k/2小的元素。如果A[k/2-1]<B[k-k/2-1], 此时是上图中绿色的部分要被扔掉,我们需要在红色的数组中求第k-(k-k/2)=k/2个元素。而如果A[k/2-1]=B[k-k/2-1], A[k/2-1]即为第k个元素。分治法解决之。

上代码

public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
		if((nums1.length+nums2.length)%2==0){
			return (findKth(nums1, nums2, (nums1.length+nums2.length)/2+1)+findKth(nums1, nums2, (nums1.length+nums2.length)/2))/2.0;    
		}
		return findKth(nums1, nums2, (nums1.length+nums2.length)/2+1);
	}
	private int findKth(int[] nums1, int[] nums2, int k){
		return findKHelper(nums1, 0, nums1.length-1, nums2, 0, nums2.length-1, k);
	}
	private int findKHelper(int[] nums1, int left1, int right1, int[] nums2, int left2, int right2, int k){
		if(left1>right1){
			return nums2[left2+k-1];
		}else if(left2>right2){
			return nums1[left1+k-1];
		}
		if(k==1){
			return Math.min(nums1[left1], nums2[left2]);
		}
		
		int search1 = k/2;
		int search2 = k-k/2;
		
		int key1 = left1+search1-1>right1?Integer.MAX_VALUE:nums1[left1+search1-1];
		int key2 = left2+search2-1>right2?Integer.MAX_VALUE:nums2[left2+search2-1];

		if(key1>key2){
			
			return findKHelper(nums1, left1, Math.min(right1, left1+search1-1), nums2, left2+search2, right2, k-search2);
		}else if(key1<key2){
			
			return findKHelper(nums1, left1+search1, right1, nums2, left2, Math.min(left2+search2-1, right2), k-search1);
		}else{
			return key1;
		}
	}
}

复杂度是k的对数,此例中k~1/2(N+M),总复杂度为log(N+M)。满足条件要求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值