leetcode 4

思路一:

1.记数组A长度为m,数组B长度为n,求中位数分两种情况,一种是元素个数为奇数,中位数为两个数组合并之后第(m+n+1)/2个元素,另一种是元素个数为偶数的情况,中位数为两个数组合并之后第(m+n+1)/2、(m+n+1)/2+1个元素。
2.所以问题转化成求两个有序数组合并后的第k或者k+1个元素。
3.注意到两个数组都是有序数组这个条件,我们需要充分利用有序这个条件,以及结合我们求解的最终问题是求解一个中位数,引导我们求解往二分的方向去思考。
4.取A[ ⌊ k / 2 ⌋ \lfloor k/2\rfloor k/2-1]和B[ ⌊ k / 2 ⌋ \lfloor k/2\rfloor k/2-1]两个元素,比较其大小。
结果有三种情况
{ 1. A [ ⌊ k / 2 ⌋ − 1 ] < B [ ⌊ k / 2 ⌋ − 1 ] 则 证 明 最 多 有 ⌊ k / 2 ⌋ + ⌊ k / 2 ⌋ − 2 个 元 素 是 于 A [ ⌊ k / 2 ⌋ − 1 ] 的 , 加 上 A [ ⌊ k / 2 ⌋ − 1 ] , 则 说 明 A [ 0 , ⌊ k / 2 ⌋ − 1 ] 的 所 有 元 素 不 可 能 是 合 并 后 的 数 组 的 第 k 个 元 素 , 故 舍 弃 掉 这 部 分 元 素 , 总 共 ⌊ k / 2 ⌋ 个 , 要 求 解 的 数 组 规 模 开 始 减 小 , 我 们 只 需 要 求 解 剩 余 数 组 中 第 k − ⌊ k / 2 ⌋ 个 元 素 即 可 。 2. A [ ⌊ k / 2 ⌋ − 1 ] > B [ ⌊ k / 2 ⌋ − 1 ] 情 况 类 似 , 只 需 要 去 掉 B [ 0 , ⌊ k / 2 ⌋ − 1 ] , 然 后 更 新 k 即 可 3. A [ ⌊ k / 2 ⌋ − 1 ] = B [ ⌊ k / 2 ⌋ − 1 ] , 可 以 归 入 小 于 的 情 况 。 \begin{cases} 1.A[\lfloor k/2\rfloor-1]<B[\lfloor k/2\rfloor-1]\\ 则证明最多有\lfloor k/2\rfloor+\lfloor k/2\rfloor-2个元素是于A[\lfloor k/2\rfloor-1]的,加上A[\lfloor k/2\rfloor-1],则说明\\A[0,\lfloor k/2\rfloor-1]的所有元素不可能是合并后的数组的第k个元素,故舍弃掉这部分元素,\\总共\lfloor k/2\rfloor个,要求解的数组规模开始减小,我们只需要求解剩余数组中第k-\lfloor k/2\rfloor个\\元素即可。\\ 2.A[\lfloor k/2\rfloor-1]>B[\lfloor k/2\rfloor-1] \\情况类似,只需要去掉B[0,\lfloor k/2\rfloor-1],然后更新k即可\\ 3.A[\lfloor k/2\rfloor-1]=B[\lfloor k/2\rfloor-1], \\可以归入小于的情况。\\ \end{cases} 1.A[k/21]<B[k/21]k/2+k/22A[k/21]A[k/21]A[0,k/21]kk/2kk/22.A[k/21]>B[k/21]B[0,k/21]k3.A[k/21]=B[k/21]
5.特殊情况
如果 A [ ⌊ k / 2 ⌋ − 1 ] 或 者 B [ ⌊ k / 2 ⌋ − 1 ] A[\lfloor k/2\rfloor-1]或者B[\lfloor k/2\rfloor-1] A[k/21]B[k/21]越界,那么我们可以选取对应数组中的最后一个元素。在这种情况下,我们必须根据排除数的个数减少 kk 的值,而不能直接将k减去 ⌊ k / 2 ⌋ \lfloor k/2\rfloor k/2
如果一个数组为空,说明该数组中的所有元素都被排除,我们可以直接返回另一个数组中第 kk 小的元素。
如果 k==1,我们只要返回两个数组首元素的最小值即可。

代码:

class Solution {
public:
    double getKnums(vector<int>& nums1, vector<int>& nums2,int k)
    {
        int m=nums1.size();
        int n=nums2.size();
        int b1=0;
        int b2=0;
        int h1=0;
        int h2=0;
        while(1)
        {
            if(b1>=m)
                return nums2[b2+k-1];
            else if(b2>=n)
                return nums1[b1+k-1];
            else if(k==1)
                return nums2[b2]<nums1[b1]?nums2[b2]:nums1[b1];
            
            h1=min(b1+k/2-1,m-1);
            h2=min(b2+k/2-1,n-1);

            if(nums1[h1]<=nums2[h2])
            {
                k-=h1-b1+1;
                b1=h1+1;
            }
            else
            {
                k-=h2-b2+1;
                b2=h2+1;
            }
        }
    }
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m=nums1.size();
        int n=nums2.size();
        if((m+n)%2)
            return getKnums(nums1,nums2,(m+n+1)/2);
        else
            return (getKnums(nums1,nums2,(m+n)/2)+getKnums(nums1,nums2,(m+n)/2+1))/2;
    }
};

思路二

利用归并排序思想求第k个元素,k为(m+n)/2或者(m+n)/2+1

代码

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m=nums1.size();
        int n=nums2.size();
        int c=(m+n)/2+1;
        int c1=0;
        int c2=0;
        int p1=0;
        int p2=0;
        while(p2+p1<c)
        {
            if(p1<m&&p2<n)
            {
                c1=c2;
                c2=nums1[p1]<nums2[p2]?nums1[p1++]:nums2[p2++];
            }
            if(p1<m&&p2>=n&&p2+p1<c)
            {
                c1=c2;
                c2=nums1[p1];
                p1++;
            }
            if(p2<n&&p1>=m&&p2+p1<c)
            {
                c1=c2;
                c2=nums2[p2];
                p2++;
            }
        }
        if((m+n)%2)
            return 1.0*c2;
        else
            return (c1+c2)/2.0;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值