Первая плохая версия

Источник: https://leetcode.com/problems/first-bad-version/
Задача. Вы разрабатываете продукт. И в какой-то момент одна из версий не проходит тесты - bad version. Все версии после нее тоже не проходят тесты и считаются bad version.
Допустим, у вас n версий продукта: [1, 2, ..., n] и вы хотите найти первую bad, которая все последующие окрасила в bad.
У вас есть функция API bool isBadVersion(version) которая возвращает значения истинно/ложно, если version является bad. 
Надо написать функцию, которая находит первую bad version. Следует мимнимизировать число вызовов API.
Пример:
Дано n = 5, and version = 4 это первая bad version (но мы об этом не знаем, нам нужно, чтобы наш алгоритм это выявил).

call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true

Значит 4 - это первая bad version. 
Идея решения: все версии идут в растущем порядке по понятным причинам. Значит, методом дихотомии (binary search, двоичный поиск) мы можем самым быстрым способом выявить первую неправильную версию за O(log(n)), потому что простраство поиска уменьшается вдвое на каждой итерации, всего итераций может быть не более n.

Компилируемое  решение:

public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
// устанавливаем границы дихотомии
        int lo = 1; // это хорошая версия
        int hi = n; // это однозначно bad версия
// все плохие версии находятся во второй части массива
        while (lo < hi) {
// выбираем значение по центру границ дихотомии
            int mid = lo + ((hi-lo)>>1);
            if (isBadVersion(mid)) {
// центральное значение даёт bad, значит, переломная точка левее или mid,
// поэтому включаем это значение в следующую итерацию
                hi = mid;
            } else {
// центральное значение даёт хорошую версию, значит, искомая точка однозначно правее
                lo = mid+1;
            }
        }
// нарушено условие lo < hi, значит мы нашли самую первую точку с bad версией,
// и она как раз в том искаженном индексе lo, который обычно содержал хорошие верссии.
        return lo;
    }
}

Результат:
Runtime: 10 ms, faster than 99.88% of Java online submissions for First Bad Version.
Memory Usage: 33.2 MB, less than 100.00% of Java online submissions for First Bad Version.

Комментарии

Популярные сообщения из этого блога

Разбиение числа на сумму с максимальным произведнием слагаемых

Число подмассивов, в которых сумма элементов равна k

Сложить два числа, которые представлены списком