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.
You have
nversions numbered from1ton. You want to find out the first bad version—the smallest version number for whichisBadVersion(version)returnstrue.Implement a function
firstBadVersion(n)that returns this first bad version. You may call the provided APIbool isBadVersion(int version).
- Versions are linearly ordered and “good” versions (
false) come before the first bad version, and all versions after it are bad (true). - We’re looking for the leftmost
truein a boolean array of lengthn. - Binary search finds that boundary in O(log n) by repeatedly halving the search space.
- Check versions
1, 2, 3, …until you find the first bad one.
int firstBadVersionBrute(int n) {
for (int v = 1; v <= n; ++v) {
if (isBadVersion(v))
return v;
}
return -1; // should never happen if at least one is bad
}- Time Complexity: O(n)
- Space Complexity: O(1)
Too slow if
nup to 10⁹.
int firstBadVersion(int n) {
int low = 1, high = n;
while (low <= high) {
int mid = low + (high - low) / 2;
if (isBadVersion(mid)) {
// mid might be first bad, but search left half
high = mid - 1;
} else {
// mid is good, so first bad is to the right
low = mid + 1;
}
}
// low is the smallest index such that isBadVersion(low) == true
return low;
}-
Key: On
true, movehigh = mid - 1; onfalse,low = mid + 1. -
After the loop,
lowpoints to the firsttrue. -
Time Complexity: O(log n)
-
Space Complexity: O(1)
#include <bits/stdc++.h>
using namespace std;
// Simulation of the API; we store the first bad version:
int FIRST_BAD;
// Mocked API:
bool isBadVersion(int version) {
return version >= FIRST_BAD;
}
/**
* Finds the first bad version in [1..n] using binary search.
*/
int firstBadVersion(int n) {
int low = 1, high = n;
while (low <= high) {
int mid = low + (high - low) / 2;
if (isBadVersion(mid)) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
// Read total number of versions and the first bad version index
// Format: n FIRST_BAD
cin >> n >> FIRST_BAD;
int result = firstBadVersion(n);
cout << result << "\n";
return 0;
}| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Binary search loop | O(log n) | O(1) |
| API calls | up to O(log n) | — |
| Overall | O(log n) | O(1) |
- Overflow‑safe mid: use
mid = low + (high−low)/2instead of(low+high)/2. - Always verify loop invariant: after each iteration, the first bad version remains within
[low…high+1]. - At the end,
lowis the smallest index whereisBadVersion(low) == true.
- First/Last occurrence of any boolean predicate over an indexed range.
- Minimum capacity / maximum threshold problems (search on a monotonic predicate).
- Search in rotated array with a custom boundary condition.
Q1. Why return
lowinstead ofhigh + 1?After the loop,
highpoints to the lastfalse(good), sohigh + 1 == lowis the firsttrue.
Q2. What if no version is bad?
Problem guarantees at least one bad. Otherwise you’d check
low <= nand return-1iflow > n.
Q3. Can the API calls be expensive?
Minimize them via binary search (~30 calls for n up to 10⁹).
Q4. How to handle 1‑based vs 0‑based versions?
Adjust initial
low/highaccordingly; here we assume 1‑based.