单个元素
目的:在一个不重复的序列里,找一个元素,找不到返回-1。
// A:元素所在数组 [x,y):区间 v:元素值
int bserach(int* A, int x, int y, int v) {
int m;
while (x < y) {
m = x + (y - x) / 2;
if (A[m] == v) return m;
else if (A[m] > v) y = m;
else x = m + 1;
}
return -1;
}
思路就很明了了。
找下界
目的:当v存在时返回它出现的第一个位置。如果不存在,返回这样一个下标i:在此处插入v(此处元素往后移)后序列仍有效。
int lower_bound(int* A, int x, int y, int v) {
int m;
while (x < y) {
m = x + (y - x) / 2;
if (A[m] >= v) y = m;
else x = m + 1;
}
return x;
}
这就有点说头了。(引自 aoapc2 by LRJ)
首先,最后的返回值不仅可能是x, x+1, x+2, …, y-1, 还可能是y——如果v大于A[y-1],就只能插入这里了。这样,尽管查找区间试左闭右开区间[x,y),返回值的候选区间却是闭区间[x,y]。A[m]和v的各种关系所带来的影响如下。
- A[m] = v: 至少已经找到一个,而左边可能还有,因此区间变为[x,m]。
- A[m] > v: 所求位置不可能在后面,但有可能是m,因此区间变为[x,m]。
- A[m] < v: m和前面都不可行,因此区间变为[m+1,y]。
求上界
目的:当v存在时返回它出现的最后位置。如果不存在,返回这样一个下标i:在此处插入v(此处元素往后移)后序列仍有效。
int upper_bound(int* A, int x, int y, int v) {
int m;
while (x < y) {
m = x + (y - x) / 2;
if (A[m] <= v) x = m+1;
else y = m;
}
return x;
}
同样,查找区间为[x,y),而返回值的候选区间是[x,y]。
因此,A[m]和v的各种关系所带来的影响如下:
- A[m] = v: 至少已经找到一个,而右边可能还有,所以区间变为[m+1,y]。
- A[m] < v: m没可能,左边也没可能,所以区间变为[m+1,y]。
- A[m] > v: m依旧有可能,右边没可能,所以区间变为[x,m]。