二分查找模板
以下程序,需给定一个单调不下降整形数组A
,整形变量l
、r
、v
,程序保证返回值i
落于闭区间 [l
, , ,r
] 中。
假定 [l
, , ,r
] 中一定存在一个 i
,
i
满足A[i]<v
且i
最小 (即序列A
的左端点):return l;
i
满足A[i]<v
且i
最大 (即v
在A
中的前驱):
while (l < r) {
int mid = l + r + 1 >> 1;
if (A[mid] < v) l = mid; else r = mid - 1;
}
return l;
i
满足A[i]≤v
且i
最小 (即序列A
的左端点):return l;
i
满足A[i]≤v
且i
最大 (即v
或v
的前驱):
while (l < r) {
int mid = l + r + 1 >> 1;
if (A[mid] <= v) l = mid; else r = mid - 1;
}
return l;
i
满足A[i]>v
且i
最小 (即v
在A
中的后继):
while (l < r) {
int mid = l + r >> 1;
if (A[mid] > v) r = mid; else l = mid + 1;
}
return l;
i
满足A[i]>v
且i
最大 (即序列A
的右端点):return r;
i
满足A[i]≥v
且i
最小 (即v
或v
的后继):
while (l < r) {
int mid = l + r >> 1;
if (A[mid] >= v) r = mid; else l = mid + 1;
}
return l;
i
满足A[i]≥v
且i
最大 (即序列A
的右端点):return r;
可能的实现
#include <algorithm>
template<class itr, class T>
itr lower_bound(itr first, itr last, const T &value){
while (std::distance(first, last)) {
itr mid = first;
std::advance(mid, std::distance(first, last) / 2);
if (*mid < value)
first = ++mid;
else last = mid;
}
return first;
}
#include <algorithm>
template<class itr, class T>
itr upper_bound(itr first, itr last, const T &value){
while (std::distance(first, last)) {
itr mid = first;
std::advance(mid, std::distance(first, last) / 2);
if (!(value < *mid))
first = ++mid;
else last = mid;
}
return first;
}
二分查找
Binary Search
本文意在一举解决读者可能遇到的:
1. 写出错误的二分查找
2. 不知道如何使用二分查找
等一系列与二分法相关的可能的问题。当然,笔者能力有限,如有不足,望海涵。
问题引入
leading-in
给定长度为 n n n 的上升序列 A A A,即 A A A 中任意一对元素 a i , a j a_i,a_j ai,aj, i < j i < j i<j 都满足 a i < a j a_i < a_j ai<aj,现在有 T T T 个询问,每个询问都会给出一个整数 b b b,你需要回答 b b b 在 A A A 当中的位置,若 b ∉ A b \not\in A b∈A,则回答 − 1 -1 −1。
朴素查找
对于第 t t t 次询问 b t b_t bt,我们可以顺序的取遍 A A A 中的每一个元素,直至第 i i i 个元素 a i = b t a_i = b_t ai=b