Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 23c0c34

Browse files
LeetCode problem: 278. First Bad Version
1 parent 7cd3cc9 commit 23c0c34

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 278. First Bad Version
2+
3+
Difficulty: `Easy`
4+
Topics: `Binary Search`, `Interactive`
5+
6+
You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of
7+
your product fails the quality check. Since each version is developed based on the previous version, all the versions
8+
after a bad version are also bad.
9+
10+
Suppose you have `n` versions `[1, 2, ..., n]` and you want to find out the first bad one, which causes all the
11+
following ones to be bad.
12+
13+
You are given an API `bool isBadVersion(version)` which returns whether `version` is bad. Implement a function to find
14+
the first bad version. You should minimize the number of calls to the API.
15+
16+
**Example 1:**
17+
18+
```text
19+
Input: n = 5, bad = 4
20+
Output: 4
21+
Explanation:
22+
call isBadVersion(3) -> false
23+
call isBadVersion(5) -> true
24+
call isBadVersion(4) -> true
25+
Then 4 is the first bad version.
26+
```
27+
28+
**Example 2:**
29+
30+
```text
31+
Input: n = 1, bad = 1
32+
Output: 1
33+
```
34+
35+
**Constraints:**
36+
37+
- `1 <= bad <= n <= 2^31 - 1`
38+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.borrelunde.leetcodesolutions.problem0278.firstbadversion;
2+
3+
/**
4+
* This is the solution to the LeetCode problem: 278. First Bad Version
5+
*
6+
* @author Børre A. Opedal Lunde
7+
* @since 2024年02月18日
8+
*/
9+
public class Solution extends VersionControl {
10+
11+
public int firstBadVersion(int n) {
12+
13+
// Low and high boundaries for the binary search.
14+
int low = 1; // Versions start from 1, not 0.
15+
int high = n;
16+
17+
// Binary search to find the first bad version.
18+
while (low <= high) {
19+
20+
// Calculate middle and avoid integer overflow. Bitwise right shift
21+
// (>> 1) is used instead of dividing by 2.
22+
final int middle = low + ((high - low) >> 1);
23+
24+
// Narrow the search based on the version check.
25+
if (isBadVersion(middle)) {
26+
// Adjust the search to the left half (exclude this version).
27+
high = middle - 1;
28+
} else {
29+
// Adjust the search to the right half (exclude this version).
30+
low = middle + 1;
31+
}
32+
}
33+
34+
// At the end of the loop, low is the first bad version.
35+
return low;
36+
}
37+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.borrelunde.leetcodesolutions.problem0278.firstbadversion;
2+
3+
/**
4+
* This is the parent class that holds the isBadVersion API for the problem. It
5+
* is needed for the unit tests.
6+
*
7+
* @author Børre A. Opedal Lunde
8+
* @since 2024年02月18日
9+
*/
10+
public class VersionControl {
11+
12+
private int badVersion;
13+
14+
public void setBadVersion(final int bad) {
15+
this.badVersion = bad;
16+
}
17+
18+
public boolean isBadVersion(int version) {
19+
return version >= badVersion;
20+
}
21+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.borrelunde.leetcodesolutions.problem0278.firstbadversion;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Test;
5+
6+
import static org.junit.jupiter.api.Assertions.assertEquals;
7+
8+
/**
9+
* This is the test to the LeetCode problem: 278. First Bad Version
10+
*
11+
* @author Børre A. Opedal Lunde
12+
* @since 2024年02月18日
13+
*/
14+
@DisplayName("First bad version")
15+
class SolutionTest {
16+
17+
private final Solution solution = new Solution();
18+
19+
@Test
20+
@DisplayName("Example one")
21+
void exampleOne() {
22+
int n = 5;
23+
int bad = 4;
24+
25+
solution.setBadVersion(bad);
26+
27+
int expected = bad;
28+
int actual = solution.firstBadVersion(n);
29+
30+
assertEquals(expected, actual);
31+
}
32+
33+
@Test
34+
@DisplayName("First version is bad")
35+
void firstVersionIsBad() {
36+
int n = 1;
37+
int bad = 1;
38+
39+
solution.setBadVersion(bad);
40+
41+
int expected = bad;
42+
int actual = solution.firstBadVersion(n);
43+
44+
assertEquals(expected, actual);
45+
}
46+
47+
@Test
48+
@DisplayName("Last version is bad")
49+
void lastVersionIsBad() {
50+
int n = Integer.MAX_VALUE;
51+
int bad = Integer.MAX_VALUE;
52+
53+
solution.setBadVersion(bad);
54+
55+
int expected = bad;
56+
int actual = solution.firstBadVersion(n);
57+
58+
assertEquals(expected, actual);
59+
}
60+
61+
@Test
62+
@DisplayName("Bad version is in the middle of many")
63+
void badVersionIsInTheMiddleOfMany() {
64+
int n = 1_000_000;
65+
int bad = 500_000;
66+
67+
solution.setBadVersion(bad);
68+
69+
int expected = bad;
70+
int actual = solution.firstBadVersion(n);
71+
72+
assertEquals(expected, actual);
73+
}
74+
75+
@Test
76+
@DisplayName("Bad version is minimum and n is maximum")
77+
void badVersionIsMinimumAndNIsMaximum() {
78+
int n = Integer.MAX_VALUE;
79+
int bad = 1;
80+
81+
solution.setBadVersion(bad);
82+
83+
int expected = bad;
84+
int actual = solution.firstBadVersion(n);
85+
86+
assertEquals(expected, actual);
87+
}
88+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /