lower_bound()
與 upper_bound()
能在指定的範圍中,找到比給定值
以下示範如何用 upper_bound()
找到比指定值
#include <algorithm>
int n, k;
int ary[N];
vector<int> v;
陣列版本:
// 先 sort 以滿足使用前提
sort(ary, ary+n);
// 回傳會是位置,對陣列而言是 pointer
// 範圍左包含、右不包含,k 是詢問值,upper_bound 回傳比 k 大的第一個元素
auto it = upper_bound(ary, ary+n, k);
// 回傳的位置為指定範圍最右側(即不包含的位置)時表示找不到
if (it == ary+n)
{
cout << "no element larger than " << k << ".\n";
}
// pointer 透過取值運算子 * 可拿到該位置所儲存的值
// poinetr 相減可得到位置差(距離),和初始位置 ary 相減的值等同於 index
else
{
cout << "ary[" << (it-ary) << "] = " << *it << " found.\n";
}
vector<T>
版本:
// 先 sort 以滿足使用前提
sort(v.begin(), v.end());
// 回傳會是位置,對 vector 而言是 iterator
// 範圍左包含、右不包含,k 是詢問值,upper_bound 回傳比 k 大的第一個元素
auto it = upper_bound(v.begin(), v.end(), k);
// 回傳的位置為指定範圍最右側(即不包含的位置)時表示找不到
if (it == v.end())
{
cout << "no element larger than " << k << ".\n";
}
// iterator 透過取值運算子 * 可拿到其指稱元素的值
// 支援 random access 的 container 其 iterator 可透過相減得到位置差(距離)
// 和初始位置 v.begin() 相減時等同於 index
else
{
cout << "v[" << (it-v.begin()) << "] = " << *it << " found.\n";
}
lower_bound()
的用法和 upper_bound()
完全相同,差異在找到的值會是不比
lower_bound()
對指定範圍尋找最小的 upper_bound()
對指定範圍尋找最小的 實作上使用 binary search,因此前提為
指定範圍包含
注意:儘管對不支援 random access 的 iterator 也能使用,但此時無法 binary search(因為無法
前面 binary search 的章節說使用前提是搜尋範圍具備單調性,而對於詢問值 upper_bound()
為例,如果存在一個值
則說此範圍對詢問值
則此函數 upper_bound()
所求。
若今天搜尋範圍雖具備單調性或者可以 bi-partition,但不是以預設的 operator<
由小到大的形式,例如可能是由大到小,或者像字串依長度排序等形式,就必須自行指定 compare。
換句話說,當今天 upper_bound()
仍然可以運作。使用和 sort 時相同的 compare function 即可。
compare function 可透過第
auto it = upper_bound(ary, ary+n, k, comp);
compare function comp(a, b)
必須使詢問值
設函數
從上式可以想到,由於比較時是將詢問值
bool comp(const int &a, const int &b)
{
return tbl[a] < tbl[b];
}
搜尋時很直觀地會想這樣寫:
auto it = upper_bound(ary, ary+n, k, comp);
然後就出事了。為什麼?
這是因為我們想搜的是 comp(a, b)
所以
解決方法是使用任何方式生出一個
tbl[n] = k;
auto it = upper_bound(ary, ary+n, n, comp);
如此一來,搜的便是
lower_bound()
和 upper_bound()
雖可在部份情境用來做 binary search 無須自行實作,不過並不能完全取代 binary search。
原因是它強制了
回傳的形式相對不好處理,可能的坑也不少,需要特別小心地去熟悉它。
競程:三章
, 競程