【Leetcode】4. Median of Two Sorted Arrays

题目地址:

https://leetcode.com/problems/median-of-two-sorted-arrays/

给定两个升序数组 A A A B B B,求两个数组所有数的中位数。如果一共偶数个,则取最中间的两个数的平均值。

设各自的长度 n n n m m m,那么如果我们解决了对任意给定的 k k k找第 k k k小的数,这个问题就解决了。所以先考虑如何解决这个更加一般的问题。我们考虑数组 A A A B B B的各自的前 k / 2 k/2 k/2(以下的除法都是整除)个数。如果 A [ k / 2 − 1 ] < B [ k / 2 − 1 ] A[k/2-1]<B[k/2-1] A[k/21]<B[k/21],那么我们可以断言 A [ 0 ] , . . . , A [ k / 2 − 1 ] A[0],...,A[k/2-1] A[0],...,A[k/21]一定都不是答案,因为如果存在 j ≤ k / 2 − 1 j\le k/2-1 jk/21使得 A [ j ] A[j] A[j]是第 k k k小的数,由于 A [ k / 2 − 1 ] < B [ k / 2 − 1 ] A[k/2-1]<B[k/2-1] A[k/21]<B[k/21],所以比 A [ j ] A[j] A[j]还小的数的个数是小于等于 j + k / 2 − 1 < k j+k/2-1< k j+k/21<k的,这就矛盾了。所以我们就可以将 A [ 0 ] , . . . , A [ k / 2 − 1 ] A[0],...,A[k/2-1] A[0],...,A[k/21]舍去,直接从 A [ k / 2 ] A[k/2] A[k/2]开始,加上 B B B的所有数,找第 k − k / 2 k-k/2 kk/2小的数。这样就将要找第 k k k小的数转变为了要找第 k − k / 2 ≤ k / 2 + 1 k-k/2\le k/2+1 kk/2k/2+1小的数,而且重复这种操作时, k k k必然会严格下降到 1 1 1,而对于 k = 1 k=1 k=1答案是显然的。如果 A A A的长度是小于 k / 2 k/2 k/2的,那么就可以直接断定 B [ 0 ] , . . . , B [ k / 2 − 1 ] B[0],...,B[k/2-1] B[0],...,B[k/21]不可能是答案,可以直接从 B [ k / 2 ] B[k/2] B[k/2]开始和 A A A全体中寻找答案,剩下的逻辑与上面类似。代码如下:

class Solution {
 public:
  double findMedianSortedArrays(vector<int>& v1, vector<int>& v2) {
    int n = v1.size() + v2.size();
    if (n % 2)
      return find(v1, 0, v2, 0, n / 2 + 1);
    else
      return (find(v1, 0, v2, 0, n / 2) + find(v1, 0, v2, 0, n / 2 + 1)) / 2.0;
  }

  int find(vector<int>& v1, int i, vector<int>& v2, int j, int k) {
    if (v1.size() - i > v2.size() - j) return find(v2, j, v1, i, k);
    if (v1.size() == i) return v2[j + k - 1];
    if (k == 1) return v1.size() == i ? v2[j] : min(v1[i], v2[j]);
    int k1 = min((int)v1.size() - 1, i + k / 2 - 1),
        k2 = j + k - (k1 - i + 1) - 1;
    if (v1[k1] < v2[k2])
      return find(v1, k1 + 1, v2, j, k - (k1 - i + 1));
    else if (v1[k1] > v2[k2])
      return find(v1, i, v2, k2 + 1, k - (k2 - j + 1));
    else
      return v1[k1];
  }
};

时间复杂度 O ( log ⁡ ( m + n ) ) O(\log (m+n)) O(log(m+n)),空间 O ( log ⁡ k ) O(\log k) O(logk)(递归栈深度)。

时间复杂度证明:
A A A B B B的数字个数和为 N N N,则 T ( N , k ) = T ( N − k / 2 , k / 2 ) + O ( 1 ) = T ( N − k / 2 − k / 4 , k / 4 ) + O ( 2 ) = . . . = T ( N − k , 1 ) + O ( log ⁡ k ) = O ( log ⁡ k ) = O ( log ⁡ N ) T(N,k)=T(N-k/2,k/2)+O(1)\\=T(N-k/2-k/4,k/4)+O(2)\\=...=T(N-k,1)+O(\log k)=O(\log k)=O(\log N) T(N,k)=T(Nk/2,k/2)+O(1)=T(Nk/2k/4,k/4)+O(2)=...=T(Nk,1)+O(logk)=O(logk)=O(logN)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值