leecode 4. Median of Two Sorted Arrays 解题报告

朴素解法

求中位数一般是用归并排序,按照类似快排的思想求第k/2大的数。但是由于给定的两个数组都是有序的,一般第一眼看到这个问题,最先想到的就是两个数组做排序,然后输出中位数。不得不说leetcode的数据也是仁慈,居然直接就过了……这个思路实在是太简单了,就不讲了,看代码就好了。

#include <string>
#include <iostream>
#include <vector>
using namespace std;
/*
    显然,最简单的思路就是两者归并排序后直接求,得到的答案肯定是对的。
*/
class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> ans;
        unsigned int i = 0,j = 0;
        while(i<nums1.size()&&j<nums2.size())
        {
            if(nums1[i]<=nums2[j])
            {
                ans.push_back(nums1[i]);
                i++;
            }
            else
            {
                ans.push_back(nums2[j]);
                j++;
            }
        }
        while(i<nums1.size())
        {
            ans.push_back(nums1[i]);
            i++;
        }
        while(j<nums2.size())
        {
            ans.push_back(nums2[j]);
            j++;
        }

//        for(unsigned int k = 0 ; k < ans.size();k++)
//        {
//            cout<<ans[k]<<endl;
//        }
        if(ans.size()%2==0)
        {
            return (double)(ans[ans.size()/2-1]+ans[ans.size()/2])/2;
        }
        else
        {
            return ans[ans.size()/2];
        }

    }
};
int main(void)
{
    Solution s;
    vector<int> a;
    vector<int> b;
    a.push_back(1);
    a.push_back(2);
    b.push_back(3);
   // b.push_back(4);
    cout<<s.findMedianSortedArrays(a,b)<<endl;

    return 0;
}

二分法

这个是官方给的标准答案
由中位数的定义可以推广出:

  • 如果在集合中存在i将集合化为两个划分left和right,i为中位数当且仅当len(left(i))=len(right(i))且max(left(i))<=min(right(i))。
  • 由此,如果是两个有序集合,则如果把这两个有序集合都用上面这种形式来写的话,如果它们组成的大集合仍然满足上面的形式,则这两个划分所在的分界点就是中位数。问题就转化到怎么求集合的划分上来了。
  • 设这两个划分点为i,j;数组A长为n,数组B长为m,则有 i + j = n − i + m − j i+j=n-i+m-j i+j=ni+mj B [ j − 1 ] ≤ A [ i ] 以 及 A [ i − 1 ] ≤ B [ j ] B[j−1]\leq A[i] 以及 A[i-1] \leq B[j] B[j1]A[i]A[i1]B[j]
  • 所以问题就转化为了在[0,m]上搜索i,使得 B [ j − 1 ] ≤ A [ i ] 以 及 A [ i − 1 ] ≤ B [ j ] , 其 中 j = n + m − 2 i 2 B[j−1]\leq A[i] 以及 A[i-1] \leq B[j],其中j=\frac{n+m-2i}{2} B[j1]A[i]A[i1]B[j]j=2n+m2i
    标准答案给的是二分的求法,跟我想到的也一样,不过我没写出来,直接用它的吧。
def median(A, B):
    m, n = len(A), len(B)
    if m > n:
        A, B, m, n = B, A, n, m
    if n == 0:
        raise ValueError

    imin, imax, half_len = 0, m, (m + n + 1) / 2
    while imin <= imax:
        i = (imin + imax) / 2
        j = half_len - i
        if i < m and B[j-1] > A[i]:
            # i is too small, must increase it
            imin = i + 1
        elif i > 0 and A[i-1] > B[j]:
            # i is too big, must decrease it
            imax = i - 1
        else:
            # i is perfect

            if i == 0: max_of_left = B[j-1]
            elif j == 0: max_of_left = A[i-1]
            else: max_of_left = max(A[i-1], B[j-1])

            if (m + n) % 2 == 1:
                return max_of_left

            if i == m: min_of_right = B[j]
            elif j == n: min_of_right = A[i]
            else: min_of_right = min(A[i], B[j])

            return (max_of_left + min_of_right) / 2.0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值