如标题,比如两个数组
a=[1,2,3]
b=[4,5,6]
k=5 ,然后归并后就是[1,2,3,4,5,6] 第5小是5
显然按照归并排序的方式可以O(n)求,可是这样顺便把所有的k对应的答案都求出来了,浪费了时间,如何在O(logn)的复杂度求出?
首先我们令
x=在a数组取出的个数
y=在b数组取出的个数
总共取出了从小到大的k个,显然k=x+y
然后呢,我们令x为二分的值
我们先考虑一下x的范围(这个问题需要把范围设置好,否则会炸)
x显然最小是max(0,k-(b数组长度)) x显然最大是min(k,(a数组的长度))
既然是二分,那肯定要考虑判定条件了
if k-mid==(b数组的长度) 真的需要从b数组取这么多吗 那还是把mid增大把,把l=mid+1
if a[mid]<=b[k-mid+1] 貌似是符合从小到大的顺序的 记录答案 l=mid+1
否则 r=mid-1
然后,主要二分代码来了
while(l<=r){
int mid=l+(r-l)/2;
if(k-mid==n2||a[mid]<=b[k-mid+1]){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
最后ans代表从a数组取的个数
那么需要考虑一下最后答案输出啥了
如果ans=0,那么是从b数组取出k个 显然cout<<b[k]
如果ans=k,那么是从a数组取出k个 显然cout<<a[k]
其他情况,emmm 从a中取出ans个,那么就是从b中取出了k-ans个,由于两个数组前b个和前k-ans个前后顺序是不一样的,但是答案肯定是这两块最大的一个(记住,两个数组原来是有序的,所以是这样)
那么就cout<<max(a[ans],b[k-ans])
结束了,noip2019(貌似改名字了)加油!!!