First Bad Version
š Problem Statement
You are given versions of a software product [1, 2, ..., N]. If a version is bad, all subsequent versions are also bad. You have a helper function is_bad_version(version) that returns True if a version is bad and False if it is good. Write a function to find the first bad version while minimizing the number of API calls.
Constraint: You must achieve time complexity.
š” Intuition
Since the versions go from all "good" to all "bad" at a specific point, the results of is_bad_version look like a sorted boolean array (e.g., [False, False, True, True, True]). Because this sequence is strictly ordered, we can apply Binary Search to find the exact boundary where False turns to True, effectively cutting the search space in half with every check.
š§ Approach
- Initialize two pointers:
first_version = 1andlast_version = nto represent the search space. - Run a
whileloop as long asfirst_version < last_version. - Calculate the
midpoint. - Call the API:
is_bad_version(mid). - If it returns
True, the first bad version is either thismidversion or something before it. Narrow the search to the left half by settinglast_version = mid. - If it returns
False, the current version is good, meaning the first bad version must be strictly after it. Narrow the search to the right half by settingfirst_version = mid + 1. - When the two pointers meet, they will land exactly on the first bad version.
ā” Complexity Analysis
ā We divide the search space in half during every iteration, vastly outperforming a linear scan.
ā We only use a few integer variables (first_version, last_version, mid) to track our position.
ā ļø Common Mistakes
- Setting
last_version = mid - 1whenis_bad_version(mid)isTrue. Ifmidhappens to be the very first bad version, subtracting 1 completely removes the correct answer from the search space. - Using a standard Binary Search
while first_version <= last_versioncondition, which can easily lead to an infinite loop when shifting boundaries without+1or-1. Using<guarantees termination when they meet. - Integer overflow in other languages: While Python handles arbitrarily large integers, in languages like Java or C++,
(left + right) / 2can cause an overflow error. The safer formula isleft + (right - left) / 2.
šÆ Final Thoughts
This pattern is known as "Binary Search for a Boundary" or "Binary Search on an Answer." It is incredibly versatile and appears constantly in systems engineering, such as finding the exact commit where a bug was introduced (which is exactly how the git bisect command works under the hood).