search and sort [2]

Median of Two Sorted Arrays

我们把问题简化,找两排好序数组的第k小的数。

  1. 从前向后取,直到取到第k小的数,时间复杂度O(k)

    “`c++
    class Solution {
    public:
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
    //merge first
    if ((m + n) % 2 == 0)
    return double(find((m + n) / 2, A, m, B, n) + find((m + n) / 2 + 1, A, m, B, n)) * 0.5;
    else
    return double(find((m + n) / 2 + 1, A, m, B, n));
    }
    int find(int k, int A[], int m, int B[], int n) {
    int count = 0, now = INT_MIN;
    int i, j;
    for (i = 0, j = 0; i < m && j < n;) {
    if (A[i] < B[j]) {
    ++i;
    now = A[i-1];
    }
    else {
    ++j;
    now = B[j-1];
    }
    ++count;
    if (count == k) return now;
    }
    if (i == m)
    return B[j + k - count - 1];
    else
    return A[i + k - count - 1];
    }
    };

 2. 二分法

    第一个数组找 k/2 小的数 A[k / 2 - 1],和第二个数组的 k / 2 小的数 B[k / 2 - 1],如果第一个数小,说明答案不可能在第一个数组前 k / 2 个数中;同理,。。。;如果两个数相等,说明这两个数就是我们要找的数。
    但是有好多边界条件需要考虑:

 - [1], [2,3,4,5,6] 让找第4小的数
 - [], [2,3,4] 让找第2小的数
 - 递归终止应该是k=1的时候,因为k=1,halfk_b = 0, halfk_a = 1, 无限循环了。

```c++
class Solution {
public:
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
        if ((m + n) % 2 == 0) {
            int l = find((m + n) / 2, A, m, B, n);
            int r = find((m + n) / 2 + 1, A, m, B, n);
            return double(l + r) / 2.0;
        } else {
            return double(find((m + n) / 2 + 1, A, m, B, n));
        }
    }
    int find(int k, int A[], int m, int B[], int n) {
        if (k > m + n) return INT_MIN;
        if (m < n) return find(k, B, n, A, m);  //确保A长
        if (n == 0) return A[k-1];
        if (k == 1) return min(A[0], B[0]);

        int halfk_b = min(k / 2, n);  //B短,不能随便取
        int halfk_a = k - halfk_b;

        if (A[halfk_a - 1] < B[halfk_b - 1])  //a中的前k/2个数是不可能有答案的了
            return find(k - halfk_a, A + halfk_a, m - halfk_a, B, n);
        else if (A[halfk_a - 1] > B[halfk_b - 1])
            return find(k - halfk_b, A, m, B + halfk_b, n - halfk_b);
        else
            return A[halfk_a - 1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值