Вы можете решить проблему с помощью бинарного поиска или решить ее в O (lg (n)), не рассматривая так много граничных случаев. Идея состоит в том, чтобы использовать бинарный поиск, чтобы найти самый низкий элемент, больший или равный значению привязки (назовем его x
).
pair<int, int> FindInterval(const vector<int>& v, int x) {
int low = 0, high = (int)v.size();
while (low < high) {
const int mid = (low + high) / 2;
if (v[mid] < x) low = mid + 1;
else high = mid;
}
// This if is used to detect then a bound (a <= x <= x) is impossible but a
// bound (x <= x <= can be found).
if (low == 0 && low < (int)v.size() && v[low] == x) ++low;
return make_pair(low - 1, low);
}
Обратите внимание, что ответом может быть (-1, 0)
, что означает отсутствие нижней границы для интервала, это может быть (n - 1, n)
, что означает отсутствие верхней границы для интервала (где n
- это размер v
). Кроме того, возможны два возможных ответа, если x
находится в v
, и может быть несколько ответов, если x
многократно в v
, потому что границы включают крайние значения.
Наконец, вы можете заменить двоичный поиск функцией std::lower_bound
:
pair<int, int> FindInterval(const vector<int>& v, int x) {
// This does the same as the previous hand-coded binary search.
const int low = (int)(lower_bound(v.begin(), v.end(), x) - v.begin());
// The rest of the code is the same...
}