133 lines
2.8 KiB
Markdown
133 lines
2.8 KiB
Markdown
# Leetcode First-Bad-Version
|
||
|
||
#### 2022-07-09 09:52
|
||
|
||
> ##### Algorithms:
|
||
> #algorithm #binary_search
|
||
> ##### Data structures:
|
||
> #DS #array
|
||
> ##### Difficulty:
|
||
> #coding_problem #difficulty-easy
|
||
> ##### Additional tags:
|
||
> #leetcode
|
||
> ##### Revisions:
|
||
> N/A
|
||
|
||
##### Related topics:
|
||
```expander
|
||
tag:#binary_search
|
||
```
|
||
|
||
|
||
|
||
##### Links:
|
||
- [Link to problem](https://leetcode.com/problems/first-bad-version/)
|
||
___
|
||
### Problem
|
||
|
||
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.
|
||
|
||
#### Examples
|
||
|
||
**Example 1:**
|
||
|
||
**Input:** n = 5, bad = 4
|
||
**Output:** 4
|
||
**Explanation:**
|
||
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
|
||
|
||
#### Constraints
|
||
|
||
- `1 <= bad <= n <= 231 - 1`
|
||
|
||
### Thoughts
|
||
|
||
> [!summary]
|
||
> This is a #binary_search problem
|
||
|
||
Note that [[Leetcode First-Bad-Version#Constraints]], n can be 2**31, which means there might be integer overflow.
|
||
|
||
To address that, according to [[Binary Search Algorithm#How to implement Binary search]], use `mid = l + (r - l) / 2`
|
||
|
||
In my first iteration,
|
||
I use a `first` variable to keep track of the first bad version.
|
||
|
||
Later I realized that by the definition of Bi-search, left boundary will converge to the first one.
|
||
|
||
### Solution
|
||
|
||
Second version, 0ms
|
||
```cpp
|
||
// The API isBadVersion is defined for you.
|
||
// bool isBadVersion(int version);
|
||
|
||
class Solution {
|
||
public:
|
||
int firstBadVersion(int n) {
|
||
// variant of BS
|
||
// 1-indexed
|
||
|
||
int r = n;
|
||
int l = 1;
|
||
int mid;
|
||
|
||
do {
|
||
mid = l + (r - l) / 2;
|
||
|
||
if (isBadVersion(mid)) {
|
||
// Search left
|
||
r = mid - 1;
|
||
} else {
|
||
l = mid + 1;
|
||
}
|
||
} while (l <= r);
|
||
|
||
return l;
|
||
}
|
||
};
|
||
```
|
||
|
||
First iteration, 4ms
|
||
```cpp
|
||
// The API isBadVersion is defined for you.
|
||
// bool isBadVersion(int version);
|
||
|
||
class Solution {
|
||
public:
|
||
int firstBadVersion(int n) {
|
||
// variant of BS
|
||
// 1-indexed
|
||
|
||
int r = n;
|
||
int l = 1;
|
||
int mid;
|
||
int first = n;
|
||
|
||
do {
|
||
mid = l + (r - l) / 2;
|
||
|
||
if (isBadVersion(mid)) {
|
||
first = min(n, mid);
|
||
// Search left
|
||
r = mid - 1;
|
||
} else {
|
||
l = mid + 1;
|
||
}
|
||
} while (l <= r);
|
||
|
||
return first;
|
||
}
|
||
};
|
||
``` |