[LeetCode]Median of Two Sorted Arrays

来源:互联网 发布:如何评价蒋方舟 知乎 编辑:程序博客网 时间:2024/04/30 09:29

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 arrays. The overall run time complexity should be O(log (m+n)).


这题的思路是这样的:

假如a或者b为空,就调用helper1函数,取另一个数组的中位数。记得分清总长度的奇偶,返回结果。

假如a和b都不是空的,则如下考虑:


在最开始的时候,我们取中位数的序号k = (m + n + 1) / 2,也就是说,想要取出两个数组中第k小的元素。这里k是从1开始算的。

接着,我们取ka和kb,作为k在数组a和b中的迭代器。只要我们保持ka+kb=k,那么要找的第k小的元素就始终保持在搜索范围之内。

这里ka和kb也是从1开始计算。

另外还定义了ms和ns,代表a数组和b数组的起始位置——ms和ns之前的元素被二分法排除;

而mt和nt表示当前数组剩余的元素个数——代表ms+mt和ns+nt之后的元素被二分法排除。

当a[ms+ka - 1] < b[ns + kb - 1],就意味着a中剩余元素的前ka个被排除,并且b中剩余元素则剩下kb个。于是,k的值就减去ka,进入下一轮循环。

我们不断地减小k的值,直到k=1.


当循环结束时,k=1,也就是说只要取出a和b中剩余元素中最小的那一个,就是我们要找的第(m+n+1)/2个元素,即中位数。

假如m+n是偶数,那么这时我们要把第k个元素和第k+1个元素取均值作为答案。


好像写的很混乱……


double helper1(int a[], int ms, int m, int k, int odd){    if (!m) return 0.;    if (odd) return a[ms + k - 1];    else return (a[ms + k - 1] + a[ms + k]) / 2.;}double helper2(int a[], int m, int b[], int n){    int ms = 0, ns = 0, mt = m, nt = n; // a和b的起点、剩余长度    int small1 = 0, small2 = 0; // 中位数    int k = (m + n + 1) / 2, ka, kb; // 查找第k个元素的迭代器    bool odd = (m + n) & 1; // m+n是否奇数    if (!m) return helper1(b, 0, n, k, odd); // 假如a是空的,就取b的中位数(第k个)    if (!n) return helper1(a, 0, m, k, odd); // 假如b是空的,就取a的中位数(第k个)    while (k > 1) {        if (mt < nt) { // 为了防止ka、kb越界,先取较小的数组a的中位数作为迭代器ka,再由k-ka得到kb,这样kb肯定也不会越界            ka = (mt + 1) / 2;            kb = k - ka;        } else {            kb = (nt + 1) / 2;            ka = k - kb;        }        if (a[ms + ka - 1] < b[ns + kb - 1]) { // a的值小,把a的前一半和b的后一半排除掉            k  -= ka; // 因为a的当前值小,所以排除掉a的前ka个元素,这样下次寻找的时候就找第k-ka个元素            ms += ka; // a的前ka个元素排除掉,因此a数组的起始位置右移ka个            mt -= ka; // a数组的剩余元素个数减去ka            nt  = kb; // b数组只剩kb个元素        } else {            k  -= kb;            ns += kb;            nt -= kb;            mt  = ka;        }        if (!mt) return helper1(b, ns, nt, k, odd); // 发现a已经排除完了,就只要在b里面找第k个元素        if (!nt) return helper1(a, ms, mt, k, odd);    } // 循环结束,此时的k必定等于1    if (a[ms] < b[ns]) { //找出a和b剩余元素中的最小值和次小值        small1 = a[ms];        small2 = b[ns];        if (ms < m - 1) small2 = std::min(b[ns], a[ms + 1]);    } else {        small1 = b[ns];        small2 = a[ms];        if (ns < n - 1) small2 = std::min(a[ms], b[ns + 1]);    }    if (odd) return small1; // 返回中位数    else return (small1 + small2) / 2.;}class Solution {public:    double findMedianSortedArrays(int A[], int m, int B[], int n) {        // Note: The Solution object is instantiated only once and is reused by each test case.        return helper2(A, m, B, n);    }};

原创粉丝点击