【AcWing刷题日记】两个升序数组求中位数

题目

在这里插入图片描述

这个还是一个分治的问题,但是难点在于分谁。
一般的做题思路是对数组进行二分,但是这个题却要对查找的中间这个数进行二分,比较反常理所以比较难。

leetcode上也同样有这个题目:
在这里插入图片描述
如果把两个数组遍历一遍,放在同一个数组里。那这样空间和时间都占有了 O ( m + n ) O(m+n) O(m+n)
但如果直接比较的过程中输出第 ( m + n + 1 ) / 2 (m+n+1)/2 (m+n+1)/2个数,空间降低到 O ( 1 ) O(1) O(1)了,但时间方面还是 O ( m + n ) O(m+n) O(m+n)。所以要用分治的想法将其变为 O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n))

但就像之前说的,第一个难点在于将找中位数的问题变为找两个数组中第K数,然后想到对K这个数进行二分。
第二个难点当然就在于想到二分K后,怎么再具体的实现。

比较两个数组k / 2处的值,如果A[k/2]大于B[k/2],那么最糟糕的情况,就是B[k/2]前边的数和A[k/2]前边的数都比B[k/2]小。那也才k-2个数,达不到第K个数。因此B[k/2]及其之前的数都可以扔掉了。这就是二分K的方式。
在这里插入图片描述

但要考虑三种特殊情况:

  • 其中一个为长度为0了,直接从另一个数组找第K个数
  • k=1的时候,不用除2了,直接选两个数组分别第一个元素的最小值
  • 当选k/2的时候,如果超过了其中一个数组的长度,那就比较其结尾的数,另一个数组中索引的位置对应后移。
class Solution {
public:
    int medianSearch(vector<int>& S1 , vector<int>& S2) {
        int m = S1.size();
        int n = S2.size();
        return findKthNum(S1, 0, m-1, S2, 0, n-1, (m+n+1)/2);
    }
    int findKthNum(vector<int>& S1, int start1, int end1, vector<int>& S2, int start2, int end2, int k){
        int len1 = end1-start1+1;
        int len2 = end2-start2+1;
        if(len1==0) return S2[start2+k-1];
        if(len2==0) return S1[start1+k-1];
        if(k==1)return min(S1[start1], S2[start2]);
        
        int index1 = start1 + min(k/2, len1) -1;
        int index2 = start2 + min(k/2, len2) -1;
        if(S1[index1]<=S2[index2]){
            return findKthNum(S1, index1+1, end1, S2, start2, end2, k-(index1-start1+1));
        }else{
            return findKthNum(S1, start1, end1, S2, index2+1, end2, k-(index2-start2+1));
        }
    }
};```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小雨的杰拉多尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值