AcWing 3819. 求两升序序列的中位数(2011年408真题)

105 阅读1分钟

解法一

求两个序列的中位数,可以归约到求这两个序列的第 kk 个数。

利用分治的思想,如果 Ak2<Bk2A_{\lfloor \frac{k}{2} \rfloor} < B_{\lfloor \frac{k}{2} \rfloor},那么 AA 中前 k2{\lfloor \frac{k}{2} \rfloor} 个元素都不可能是答案

时间复杂度 O(log(m+n))O(log(m + n)),空间复杂度 O(m+n)O(m + n)

class Solution {
    int sol(vector<int> s1, vector<int> s2, int k) { //寻找第 k 个数字
        if(s1.empty()) return s2[k - 1];
        if(s2.empty()) return s1[k - 1];
        if(k == 1) return s1[0] < s2[0] ? s1[0] : s2[0];
        
        int n = s1.size(), m = s2.size();
        int i = min(n, k / 2) - 1, j = min(m, k / 2) - 1;
        if(s1[i] < s2[j]) 
            return sol(vector<int>(s1.begin() + i + 1, s1.end()), s2, k - i - 1);
        else
            return sol(s1, vector<int>(s2.begin() + j + 1, s2.end()), k - j - 1);
    }
    
public:
    int medianSearch(vector<int>& s1, vector<int>& s2) {
        int n = s1.size(), m = s2.size(), k = (n + m + 1) / 2;
        return sol(s1, s2, k);
    }
};

解法二

假设中位数在 AA 中,那么中位数 AiA_{i} 一定满足 Bki2AiBki1 B_{k-i-2}\leq A{i} \leq B_{k-i-1},利用二分枚举 ii 即可

解释如下:

A[0,i1]AiA[i+1,n1]B[0,k2i]Bki1B[ki,m1]A[0 ,i-1 ] \qquad A_{i} \qquad \qquad A[i + 1, n - 1] \\ B[0,k-2-i] \qquad B_{k - i - 1} \qquad B[k - i, m - 1]

时间复杂度 O(log(n+m))O(log(n + m)),空间复杂度 O(1)O(1)

class Solution {
    int sol(vector<int> s1, vector<int> s2, int k) {
        int n = s1.size(), m = s2.size();
        int l = 0, r = n - 1, ans = -1;
        while(r >= l and ans == -1) {
            int i = l + r >> 1, j = k - i - 1;
            if(j < 0) break; // j 下溢
            if(j == 0 and s1[i] <= s2[j]) ans =s1[i]; 
            if(j > m) break; // j 上溢
            if(s1[i] >= s2[j - 1]) {
                if(j == m) ans = s1[i];
                else {
                    if(s1[i] <= s2[j]) ans = s1[i];
                }
            }
            
            if(s1[i] > s2[j]) {
                r = i - 1;
            }
            else {
                l = i + 1;
            }
        }
        return ans;
    }
    
public:
    int medianSearch(vector<int>& s1, vector<int>& s2) {
        int n = s1.size(), m = s2.size(), k = (n + m + 1) / 2;
        int ans = sol(s1, s2, k);
        if(ans == -1) ans = sol(s2, s1, k);
        return ans;
    }
};