Problem Statement
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad.
Suppose you have n versions [1, 2, ..., n]
and you want to find out the first bad one, which causes all the following ones to be bad.
You are given an API bool isBadVersion(version)
which returns whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.
Input
n
: An integer representing the number of versions (1-indexed, so versions are1, 2, ..., n
).isBadVersion(version)
: A boolean API that returnstrue
if the given version is bad, andfalse
otherwise.
Output
- Return the smallest version number such that
isBadVersion(version) == true
.
Examples
Example 1:
Input: n = 5, bad = 4
Output: 4
Explanation:
+-----+-----+-----+-----+-----+
version = | 1 | 2 | 3 | 4 | 5 |
+-----+-----+-----+-----+-----+
Bad = False False False True True
call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true
Then 4 is the first bad version.
Example 2:
Input: n = 1, bad = 1
Output: 1
Explanation:
+-----+
version = | 1 |
+-----+
Bad = True
call isBadVersion(1) -> true
Then 1 is the first bad version.
Different Approaches
1️⃣ Binary Search
Intuition:
The problem involves finding the first bad version in a range of versions. Once a version is identified as bad, all subsequent versions are guaranteed to be bad. This gives the problem a monotonic property: if version i
is bad then all versions j
where j ≥ i
are also bad.
The goal is to find the smallest index of a bad version while minimizing the number of calls to the isBadVersion
API. A binary search is ideal because it allows us to repeatedly divide the search range in half, efficiently narrowing down the first bad version.
Approach:
- Define the Search Space: Start with the entire range of versions from
1
ton
. - Binary Search:
Calculate the middle version (
mid
) using the formula:mid = low + (high - low) / 2
- Use the API
isBadVersion(mid)
to check whether the current version is bad.- If it's bad:
- This could be the first bad version, so store it as a candidate.
- Narrow the search to the left half by updating
high = mid - 1
.
- If it's not bad:
- The first bad version must be in the right half, so update
low = mid + 1
.
- The first bad version must be in the right half, so update
- If it's bad:
- Termination: The loop stops when
low > high
. By then, the variable tracking the first bad version (badVersion
) contains the correct result.
Code:
// The API isBadVersion is defined for you.
// bool isBadVersion(int version);
class Solution {
public:
int firstBadVersion(int n) {
// Initialize the search range
int low = 1; // The lowest version to check
int high = n; // The highest version to check
int badVersion = -1; // Variable to store the first bad version, default to -1
// Perform binary search
while (low <= high) {
// Calculate the middle point of the current range
int mid = low + (high - low) / 2;
// Check if the current version is bad using the API
if (isBadVersion(mid) == true) {
// If it's bad, record it as a candidate for the first bad version
badVersion = mid;
// Move the search to the left (earlier versions) to find the first bad one
high = mid - 1;
} else {
// If it's not bad, move the search to the right (later versions)
low = mid + 1;
}
}
// Return the first bad version found
return badVersion;
}
};
Complexity Analysis:
- Time Complexity:
O(log n)
- In each iteration, we reduce the search range by half using binary search.
- Space Complexity:
O(1)