前言
退役多年后惊闻鹅厂要搞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]=mid−k,注意此处的mid为扩充后的mid,即n+m
此时二分要满足的条件为
a
i
<
b
y
a_i < b_y
ai<by 且
b
x
<
a
j
b_x < 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;
}
};