Бинарный (двоичный) поиск по ответу


Бинарный (двоичный) поиск по ответу

Существует класс задач, в которых мы можем быстро проверять является ли какое-либо значение ответом к задаче или нет. Но сам ответ быстро найти не можем. При этом, мы можем сказать, что ответ всегда лежит в определенных границах. Кроме этого, если перебирать значения линейным перебором (от минимально возможного до максимального возможного) и проверять подходит ли нам это значение в качестве ответа, то мы будем получать такие ответы: нет нет ... нет да да ... да (или наоборот, сначала да, потом нет).
В этом случае, мы можем для поиска ответа использовать двоичный поиск. 
 
Основная идея решения задачи методом двоичного поиска заключается в том, чтобы сформулировать задачу "найдите максимальное (минимальное) X, такое что какое-то свойство от X выполняется" и решить её, подбирая значение X бинпоиском.

Обычно, для нахождения ответа методом двоичного поиска, создают отдельную функцию, которая проверяет может ли являться переданное значение ответом или нет и возращает True или False.
Сам двоичный поиск будет выглядеть следующим образом (приведем 2 варианта реализации, которых достаточно для решения любой задачи).
// Функция check() возвращает 
// сначала True, потом False
// Необходимо найти 
// последний check() == True

l = 0;
r = ??? // определяется из условия
while (l + 1 < r)
{
  m = (l + r) / 2;
  if (check(m))
    l = m;
  else
    r = m;
}

if (check(r))
  ans = r;
elif (check(l))
  ans = l;
else
  ans = -1; // решения нет
// Функция check() возвращает 
// сначала False, потом True
// Необходимо найти 
// первый check() == True

l = 0
r = ??? // определяется из условия
while (l + 1 < r)
{
  m = (l + r) / 2;
  if (not check(m))
    l = m;
  else
    r = m;
}

if (check(l))
  ans = l;
elif (check(r))
  ans = r;
else
  ans = -1;  // решения нет

Значения границ (l и r) выбираются таким образом, что при значении l точно не подходит (не является решением), значение r точно подходит, хоть это значение и не является оптимальным.

Бинарный (двоичный) поиск по ответу

Существует класс задач, в которых мы можем быстро проверять является ли какое-либо значение ответом к задаче или нет. Но сам ответ быстро найти не можем. При этом, мы можем сказать, что ответ всегда лежит в определенных границах. Кроме этого, если перебирать значения линейным перебором (от минимально возможного до максимального возможного) и проверять подходит ли нам это значение в качестве ответа, то мы будем получать такие ответы: нет нет ... нет да да ... да (или наоборот, сначала да, потом нет).
В этом случае, мы можем для поиска ответа использовать двоичный поиск. 
 
Основная идея решения задачи методом двоичного поиска заключается в том, чтобы сформулировать задачу "найдите максимальное (минимальное) X, такое что какое-то свойство от X выполняется" и решить её, подбирая значение X бинпоиском.

Обычно, для нахождения ответа методом двоичного поиска, создают отдельную функцию, которая проверяет может ли являться переданное значение ответом или нет и возращает True или False.
Сам двоичный поиск будет выглядеть следующим образом (приведем 2 варианта реализации, которых достаточно для решения любой задачи).
# Функция check() возвращает 
# сначала True, потом False
# Необходимо найти 
# последний check() == True

l = 0
r = ??? # определяется из условия
while l + 1 < r:
  m = (l + r) // 2
  if check(m):
    l = m
  else:
    r = m

if check(r):
  ans = r
elif check(l):
  ans = l
else:
  ans = -1 # решения нет
# Функция check() возвращает 
# сначала False, потом True
# Необходимо найти 
# первый check() == True

l = 0
r = ??? # определяется из условия
while l + 1 < r:
  m = (l + r) // 2
  if not check(m):
    l = m
  else:
    r = m

if check(l):
  ans = l
elif check(r):
  ans = r
else:
  ans = -1 # решения нет

Значения границ (l и r) выбираются таким образом, что при значении l точно не подходит (не является решением), значение r точно подходит, хоть это значение и не является оптимальным.