У меня проблема с определением инварианта нахождения первого элемента бинарного поиска. (У меня есть отсортированный массив a, и я хочу найти первый элемент, равный некоторому числу q, и если он не существует, вернуть -1)
Во-первых, я установил этот инвариант на время.
Мой инвариант
«Всегда a[l]‹= q, а также a[r] > q» ==> «Всегда l ‹= ind, а также > ind».
В соответствии с моим инвариантом я написал этот код:
int l=0,r=n;
while(l<r){
int mid=(r+l)/2;
if(a[mid]==q){
r=mid+1;
}
else{
if(a[mid]>q){
r=mid;
}else if(a[mid]<q) l=mid+1;
}
}
return l;
Но есть проблема, что if(a[mid]==q)
тогда я должен выбрать r
, который не нарушает мой инвариант.
Если я выберу mid-1
, я нарушу его, потому что a[r]
будет ‹= q
.
И я должен перебирать свои индексы, пока не найду индекс I с a[i]>q
, а затем установить r
для этого индекса. (r=i)==>Но если я сделаю это, это не O(log n)
И я видел некоторый код, реализующий lower_bound
, который if(a[mid]==q)
устанавливает r
в mid
, но я думаю, что они нарушают их инвариант, но их код правильный и возвращает правильное значение.
Как этот код:
1- int l = 0;
2- int r = n; // Not n - 1
3- while (l < r) {
4- int mid = (l + r) / 2;
5- if (q <= a[mid]) {
6- r = mid;
7- } else {
8- l = mid + 1;
9- }
10- }
11- return l;
Во-первых, инвариант похож на мой инвариант (i
находится в диапазоне [l,r)
), но в строке 5 рассмотрим if(q==a[mid])
, тогда, очевидно, он нарушает, потому что его ([l,r]
, потому что r
равно, и это может быть первое появление).
Я прав или у меня нет правильного понимания концепции инварианта?
l < x and r >= x
, а затем, наконец, вернутьr
- person Andrew Scott   schedule 24.05.2019