题目来源:https://leetcode.com/problems/median-of-two-sorted-arrays/

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)).

解题思路:

题目是这样的:给定两个已经排序好的数组(可能为空),找到两者所有元素中第k大的元素。另外一种更加具体的形式是,找到所有元素的中位数。本篇文章我们只讨论更加一般性的问题:如何找到两个数组中第k大的元素?不过,测试是用的两个数组的中位数的题目,Leetcode第4题 Median of Two Sorted Arrays

方案1:假设两个数组总共有n个元素,那么显然我们有用O(n)时间和O(n)空间的方法:用merge sort的思路排序,排序好的数组取出下标为k-1的元素就是我们需要的答案。
这个方法比较容易想到,但是有没有更好的方法呢?
方案2:我们可以发现,现在我们是不需要“排序”这么复杂的操作的,因为我们仅仅需要第k大的元素。我们可以用一个计数器,记录当前已经找到第m大的元素了。同时我们使用两个指针pA和pB,分别指向A和B数组的第一个元素。使用类似于merge sort的原理,如果数组A当前元素小,那么pA++,同时m++。如果数组B当前元素小,那么pB++,同时m++。最终当m等于k的时候,就得到了我们的答案——O(k)时间,O(1)空间。
但是,当k很接近于n的时候,这个方法还是很费时间的。当然,我们可以判断一下,如果k比n/2大的话,我们可以从最大的元素开始找。但是如果我们要找所有元素的中位数呢?时间还是O(n/2)=O(n)的。有没有更好的方案呢?
我们可以考虑从k入手。如果我们每次都能够剔除一个一定在第k大元素之前的元素,那么我们需要进行k次。但是如果每次我们都剔除一半呢?所以用这种类似于二分的思想,我们可以这样考虑:

Assume that the number of elements in A and B are both larger than k/2, and if we compare the k/2-th smallest element in A(i.e. A[k/2-1]) and the k-th smallest element in B(i.e. B[k/2 - 1]), there are three results:
(Becasue k can be odd or even number, so we assume k is even number here for simplicy. The following is also true when k is an odd number.)
A[k/2-1] = B[k/2-1]
A[k/2-1] > B[k/2-1]
A[k/2-1] < B[k/2-1]
if A[k/2-1] < B[k/2-1], that means all the elements from A[0] to A[k/2-1](i.e. the k/2 smallest elements in A) are in the range of k smallest elements in the union of A and B. Or, in the other word, A[k/2 - 1] can never be larger than the k-th smalleset element in the union of A and B.

Why?
We can use a proof by contradiction. Since A[k/2 - 1] is larger than the k-th smallest element in the union of A and B, then we assume it is the (k+1)-th smallest one. Since it is smaller than B[k/2 - 1], then B[k/2 - 1] should be at least the (k+2)-th smallest one. So there are at most (k/2-1) elements smaller than A[k/2-1] in A, and at most (k/2 - 1) elements smaller than A[k/2-1] in B.So the total number is k/2+k/2-2, which, no matter when k is odd or even, is surly smaller than k(since A[k/2-1] is the (k+1)-th smallest element). So A[k/2-1] can never larger than the k-th smallest element in the union of A and B if A[k/2-1]<B[k/2-1];
Since there is such an important conclusion, we can safely drop the first k/2 element in A, which are definitaly smaller than k-th element in the union of A and B. This is also true for the A[k/2-1] > B[k/2-1] condition, which we should drop the elements in B.
When A[k/2-1] = B[k/2-1], then we have found the k-th smallest element, that is the equal element, we can call it m. There are each (k/2-1) numbers smaller than m in A and B, so m must be the k-th smallest number. So we can call a function recursively, when A[k/2-1] < B[k/2-1], we drop the elements in A, else we drop the elements in B.

We should also consider the edge case, that is, when should we stop?
1. When A or B is empty, we return B[k-1]( or A[k-1]), respectively;
2. When k is 1(when A and B are both not empty), we return the smaller one of A[0] and B[0]
3. When A[k/2-1] = B[k/2-1], we should return one of them

In the code, we check if m is larger than n to garentee that the we always know the smaller array, for coding simplicy.

Java实现:

 public class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length, n = nums2.length;
int k = (m + n) / 2;
if((m+n)%2==0){
return (findKth(nums1,nums2,0,0,m,n,k)+findKth(nums1,nums2,0,0,m,n,k+1))/2;
} else {
return findKth(nums1,nums2,0,0,m,n,k+1);
} } private double findKth(int[] arr1, int[] arr2, int start1, int start2, int len1, int len2, int k){
if(len1>len2){
return findKth(arr2,arr1,start2,start1,len2,len1,k);
}
if(len1==0){
return arr2[start2 + k - 1];
}
if(k==1){
return Math.min(arr1[start1],arr2[start2]);
}
int p1 = Math.min(k/2,len1) ;
int p2 = k - p1;
if(arr1[start1 + p1-1]<arr2[start2 + p2-1]){
return findKth(arr1,arr2,start1 + p1,start2,len1-p1,len2,k-p1);
} else if(arr1[start1 + p1-1]>arr2[start2 + p2-1]){
return findKth(arr1,arr2,start1,start2 + p2,len1,len2-p2,k-p2);
} else {
return arr1[start1 + p1-1];
}
}
}

LeetCode 4 Median of Two Sorted Arrays (两个数组的mid值)的更多相关文章

  1. [LeetCode] 4. Median of Two Sorted Arrays 两个有序数组的中位数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  2. [leetcode]4. Median of Two Sorted Arrays俩有序数组的中位数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  3. 【算法之美】求解两个有序数组的中位数 — leetcode 4. Median of Two Sorted Arrays

    一道非常经典的题目,Median of Two Sorted Arrays.(PS:leetcode 我已经做了 190 道,欢迎围观全部题解 https://github.com/hanzichi/ ...

  4. LeetCode(3) || Median of Two Sorted Arrays

    LeetCode(3) || Median of Two Sorted Arrays 题记 之前做了3题,感觉难度一般,没想到突然来了这道比较难的,星期六花了一天的时间才做完,可见以前基础太差了. 题 ...

  5. Leetcode 4. Median of Two Sorted Arrays(二分)

    4. Median of Two Sorted Arrays 题目链接:https://leetcode.com/problems/median-of-two-sorted-arrays/ Descr ...

  6. [LintCode] Median of Two Sorted Arrays 两个有序数组的中位数

    There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted ...

  7. 2.Median of Two Sorted Arrays (两个排序数组的中位数)

    要求:Median of Two Sorted Arrays (求两个排序数组的中位数) 分析:1. 两个数组含有的数字总数为偶数或奇数两种情况.2. 有数组可能为空. 解决方法: 1.排序法 时间复 ...

  8. LeetCode 4. Median of Two Sorted Arrays & 归并排序

    Median of Two Sorted Arrays 搜索时间复杂度的时候,看到归并排序比较适合这个题目.中位数直接取即可,所以重点是排序. 再来看看治阶段,我们需要将两个已经有序的子序列合并成一个 ...

  9. 第三周 Leetcode 4. Median of Two Sorted Arrays (HARD)

    4. Median of Two Sorted Arrays 给定两个有序的整数序列.求中位数,要求复杂度为对数级别. 通常的思路,我们二分搜索中位数,对某个序列里的某个数 我们可以在对数时间内通过二 ...

随机推荐

  1. [转载]SharePoint 2013测试环境安装配置指南

    软件版本 Windows Server 2012 标准版 SQL Server 2012 标准版 SharePoint Server 2013 企业版 Office Web Apps 2013 备注: ...

  2. Hadoop第13周练习—HBase作业

    1    :举例子说明HBase相对简单 1.1 1.2     回答 2    :设计HBase存储站内短信 2.1 2.2     回答 书面作业1:举例子说明HBase相对简单 请举出一例子,使 ...

  3. 自己动手模拟百分百<select>下拉列表

    浏览器默认的下拉确实不好用啊,主要是样式不好修改和统一. (一)下手之前先理清一下<select>的流程: 1.结构:<select> <option value=&qu ...

  4. iOS-微信支付(订单号重复的问题)

    1. 官方文档中说过同一笔交易不能多次提交,出现这个错误让核实商户订单号是否重复提交,但是有些情况下是需要重复提交的,比如:用户微信支付的时候没有付款,直接取消了,那么订单如果已经创建了,在订单中心就 ...

  5. android resources使用总结

    http://developer.android.com/guide/topics/resources/more-resources.html http://developer.android.com ...

  6. 数据库收缩:NOTRUNCATE与TRUNCATEONLY

    在进行数据库收缩时,我们有2个可用选项:NOTRUNCATE,TRUNCATEONLY.这篇文章我们会详细讨论下这2个选项的具体区别. NOTRUNCATE 当你对数据库收缩命令提供NOTRUNCAT ...

  7. 数学 --- 高斯消元 POJ 1830

    开关问题 Problem's Link: http://poj.org/problem?id=1830 Mean: 略 analyse: 增广矩阵:con[i][j]:若操作j,i的状态改变则con[ ...

  8. 译:泛型List集合转化为DateTable的扩展方法

    译文出处:http://www.codeproject.com/Tips/867866/Extension-Method-for-Generic-List-Collection-to-Da 这段代码是 ...

  9. GridView如何实现双击行进行编辑,更新

    虽然标题是原创,但是其实主要的思想呢还是接见了晓风残月的思路,今天在晓风残月的博客上看到了如何利用GridView来实现双击进行编辑.我决定动手实现一下,由于还没有实现双击进行更改操作,所以顺便就把这 ...

  10. KMP---Count the string

    题目网址:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=110060#problem/A Description It is well k ...