[LeetCode 4]Median of Two Sorted Arrays 二分查找


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

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

=======================================

题目要求O(logn)的时间求解问题,很容易想到是二分搜索的方法来做,但是不同于一般的二分,这里是有两个各自有序的数组,所以需要寻找额外的约束条件。

要求的是中位数,中位数最重要的性质是位于中间,也就是刚好将数组平分,左侧长度等于右侧长度。这是一个很重要的性质,有了这个性质,我只要二分其中一个数组的分割点,就可以求出另一数组的分割点。

再来看如何更新左界和右界使得算法进行下去。假设两数组名为A和B,长度分别为m和n,现在二分数组A的边界i,由约束条件中位数两侧长度相等,可以求得B的边界j。当i和j是正确的边界时,应该有A[i-1] <= B[j] and B[j-1]  <= A[i]。如果B[j-1] > A[i],则说明j取大了,i取小了。如果A[i-1] > B[j]说明i取大了。按照这样的规则则可以正确地二分出结果,需要注意边界条件如i=0,i=m此时不存在A[i-1]或A[i],这种情况也应该视为满足了条件。

还有一点需要注意的是,题目给了两个数组,应该二分长度较小的那个数组,否则会出现j超出了范围的问题,比如,A的长度为10,B的长度为2,当二分到i=2时,得到j=4,此时访问B[j-1]出现运行错误。(我在这里WA了两次)


最后是代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& A, vector<int>& B) {
        int m = A.size();
        int n = B.size();

        vector<int> &nums1 = m > n ? B : A;
        vector<int> &nums2 = m > n ? A : B;
        if (m > n) {
            int tmp = m;
            m = n;
            n = tmp;
        }

        int lo = 0, hi = m, half = (m + n + 1) / 2;

        int i, j;
        while (lo <= hi) {
            i = (lo + hi) / 2;
            j = half - i;

            if (j > 0 && i < m && nums2[j-1] > nums1[i]) {
                lo = i+1;
            } else if (i > 0 && j < n && nums1[i-1] > nums2[j]) {
                hi = i-1;
            } else {
                break;
            }
        }
        int max_l, min_r;


        if (i == 0) max_l = nums2[j-1];
        else if (j == 0) max_l = nums1[i-1];
        else max_l = max(nums1[i-1], nums2[j-1]);
        if ((m+n) & 1) return max_l;

        if (i == m) min_r = nums2[j];
        else if (j == n) min_r = nums1[i];
        else min_r = min(nums1[i], nums2[j]);

        return (max_l + min_r) / 2.0;
    }
};




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值