力扣丢人日记-寻找两个有序数组的中位数

前言

退役多年后惊闻鹅厂要搞wpc,赶紧开始残疾人康复训练,记录一下丢人过程,目前来看应该会主要记录一些hard难度的解题思路,尽量保证为题解复杂度,过度丢人的情况下记录一些mid/easy也不是不可能…

寻找两个有序数组的中位数`
这道题思路还是十分清晰的,就是二分,但是会有奇偶、越界等烦人的问题,所以偷偷瞄了眼题解…
对于奇偶问题,有一个比较好的思路就是把原先数组扩大两倍,很显然对应的中位数不会改变而且能避免分类讨论

对于串 a 1 , a 2 , a 3 , . . . , a n a_1, a_2, a_3, ..., a_n a1,a2,a3,...,an与串 b 1 , b 2 , b 3 , . . . , b m b_1, b_2, b_3, ..., b_m b1,b2,b3,...,bm,我们先把原来的串扩大两倍,注意我们这个扩大是虚的,并没有在原始的数组上直接做这么个操作,而是将二分下标扩大两倍然后倒推回在原数组的对应的位置,然后假定在 k k k处进行一次切割,即
a 1 , a 1 , a 2 , a 2 , . . . a i , ∣ a j , . . . , a n a_1, a_1, a_2, a_2, ... a_i, | a_j, ...,a_n a1,a1,a2,a2,...ai,aj,...,an
那么在串b的分割的位置也就能推出来了
b 1 , b 1 , b 2 , b 2 , . . . b x , ∣ b y , . . . , b n b_1, b_1, b_2, b_2, ... b_x, | b_y, ...,b_n b1,b1,b2,b2,...bx,by,...,bn
i n d e x [ b x ] = m i d − k index[b_x] = mid - k index[bx]=midk,注意此处的mid为扩充后的mid,即n+m
此时二分要满足的条件为 a i &lt; b y a_i &lt; b_y ai<by b x &lt; a j b_x &lt; a_j bx<aj 所以这个二分写起来还与传统的二分有一些不一样,在ans的左右两边都是不符合条件的,所以每次分的时候不能把Mid包入剩下的区间中。
然后还有一些边界处理的情况,防止这个分割的位置超出整个数据,这里处理还是比较简单的,看代码应该就能明白

class Solution {
public:
    double findMedianSortedArrays(vector<int>& a, vector<int>& b) {
        if (a.size() > b.size()) swap(a, b);

        int n = a.size(), m = b.size();
        assert(n <= m);

        int l = 0, r = 2 * n;
        int mid = n + m;
        int al, ar, bl, br;
        int val, var, vbl, vbr;
        while (1) {
            int m1 = (l + r) / 2;
            int m2 = mid - m1;
            al = (m1 + 1) / 2 - 1;
            ar = al + !(m1 & 1);
            bl = (m2 + 1) / 2 - 1;
            br = bl + !(m2 & 1);

            val = al < 0 ? INT_MIN : a[al];
            var = ar >= n ? INT_MAX : a[ar];
            vbl = bl < 0 ? INT_MIN : b[bl];
            vbr = br >= m ? INT_MAX : b[br];

            if (val > vbr) r = m1 - 1;
            else if (vbl > var) l = m1 + 1;
            else break;
        }
        //printf("al = %d ar = %d bl = %d br = %d l = %d r = %d\n", al, ar, bl, br, l, r);
        //printf("val = %d var = %d vbl = %d vbr = %d\n", val, var, vbl, vbr);
        return (max(val, vbl) + min(var, vbr)) / 2.0;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值