Median of Two Sorted Arrays

来源:互联网 发布:淘宝全球购是什么意思 编辑:程序博客网 时间:2024/04/28 22:42

There are two sorted arrays A and B 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)).

思路:Ref: http://blog.csdn.net/zxzxy1988/article/details/8587244

方案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.

class Solution {public:    double findMedianSortedArrays(int A[], int m, int B[], int n) {        int total = m + n;        if (total & 1)  {            return findKth(A, m, B, n, total / 2 + 1); // 如果total是奇数,中位数就是total/2+1位置上的数,即中间的数        }        else {            return (findKth(A, m, B, n, total / 2) + findKth(A, m, B, n, total / 2 + 1))/2; //如果total是偶数,中间两个数的平均数为中间数        }    }        // 寻找第k个数, k从1开始    double findKth(int* A, int m, int* B, int n, int k) {        // 总是假设参数中m要比n小,所以后面也是通过m为0判断是否将A删除完了        if (m > n) {            return findKth(B, n, A, m, k);        }                if (m == 0) {            return B[k - 1]; // 如果A已经删除完了,那么直接返回B的第k-1个即为所寻找的第k个元素(k从1开始计数)        }                // 注意m==0要放k==1前面,防止出现A[0]不存在的情况会报错;        if (k == 1) {            return min(A[0], B[0]);        }                int pa = min(k / 2, m); //  防止出现m小于k/2的情况        int pb = k - pa; // 正常情况也是k/2        if (A[pa - 1] < B[pb - 1]) {            return findKth(A + pa, m - pa, B, n, k - pa); // 删除A的前pa个,同时寻找第k-pa个        }        else if (A[pa - 1] > B[pb - 1]) {            return findKth(A, m, B + pb, n - pb, k - pb); // 删除B的前pb个,同时寻找第k-pb个        }        else {            return A[pa - 1];        }    }};


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 运输公司对车主不买保险怎么办 苹果平板限制访问密码忘了怎么办 安卓手机忘了解锁密码怎么办 海之蓝扫码显示域名不对这是怎么办 华为手机丢了帐号密码忘记了怎么办 电脑会员系统账号密码忘记了怎么办 推广渠道客户要求免费铺货怎么办 代理机构做的网站找不到人了怎么办 瓷砖买的和描述的不一样怎么办 网上买东西地址的省份写错了怎么办 驾校把预留号码注册错了怎么办 太害羞了不敢进店买东西怎么办 收件箱邮箱邮件满了但不想删怎么办 模拟人生畅玩版任务时间过了怎么办 快递放柜子里长时间不拿怎么办 古筝的筝码序号错了怎么办? 极限竞速3地平线爆内存怎么办 车载导航安卓系统禁止装软件怎么办 在微信上买东西买到假货怎么办 想从新西兰寄红酒到家运费怎么办 新买的裤子掉色把内裤染色了怎么办 白衣服变脏变黄怎么办用英文怎么说 经常宅在家里不爱出去玩怎么办 在家里呆不住老想着往外跑怎么办 新商盟网上订烟登录密码忘了怎么办 在拼多多购物质量有问题怎么办 美图手机总弹出一键加速广告怎么办 手机看小说总是喜欢弹出广告怎么办 美团外卖商家注册门头不合格怎么办 手机一打网页就自动弹出广告怎么办 美团预定的宾馆不可取消怎么办 公积金注册时的号码忘了怎么办 苹果7基带坏了修不好怎么办 苹果手机玩终结者2卡怎么办 支付宝转账转到邮箱忘记邮箱怎么办 朋友转账到我的邮箱支付宝怎么办 苹果账号密码和手机号码忘了怎么办 网上购物付款后商家不发货怎么办 夏商国际商城买到假货怎么办 重庆时时彩突然冻结账户资金怎么办 微信安全中心打不开是白色的怎么办