Держим две границы отрезка, обе включительно: lo и hi. На каждом шаге берём середину mid = (lo + hi) // 2 и сравниваем a[mid] с искомым. Возможны три случая: нашли – запоминаем позицию и выходим; a[mid] < x – искомое правее, значит lo = mid + 1; иначе – левее, значит hi = mid - 1. Цикл идёт, пока lo <= hi.
a = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]
x = 23
lo = 0
hi = len(a) - 1
pos = -1
while lo <= hi:
mid = (lo + hi) // 2
if a[mid] == x:
pos = mid
break
if a[mid] < x:
lo = mid + 1
else:
hi = mid - 1
print(pos) # 5
Прогон для x = 23:
| Шаг | lo | hi | mid | a[mid] | Что происходит |
|---|---|---|---|---|---|
| 1 | 0 | 9 | 4 | 16 | 16 < 23, идём правее: lo = 5 |
| 2 | 5 | 9 | 7 | 56 | 56 > 23, идём левее: hi = 6 |
| 3 | 5 | 6 | 5 | 23 | нашли, pos = 5 |
Три проверки вместо десяти.