Description
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.
Constraints
1 <= bad <= n <= 231 - 1
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
Solution 1: Brute-Force
Steps
- The most intuitive and basic solution is to iterate from version
1
to versionn
sequentially and check one by one. IfisBadVersion
returnsTrue
, then immediately returns the current version.
Codes
def first_bad_version(n: int) -> int:
for version in range(1, n + 1):
if isBadVersion(version):
return version
PythonComplexities
- Time Complexity:
O(N)
, where N isn
. - Space Complexity:
O(1)
Solution 2: Binary Search
Thought
According to the requirements of the problem, we need to find a specific target within a range ([1, 2, ..., n]
) where the elements in the array are sorted. This gives us enough hints to use binary search. During each search, we continually narrow down the search range, getting closer to the target we are looking for.
Steps
- Use two pointers,
left
andright
, to represent the left and right boundaries of the current search range. - When
left
is less than or equal toright
:- Calculate the midpoint
mid
of the current range asmid = (left + right) // 2
. - Check the version pointed to by
mid
. If it is a normal version (isBadVersion(mid) == False
), it means that all versions beforemid
are also normal and can be skipped. Move theleft
pointer to the element immediately aftermid
. - If
mid
points to a bad version (isBadVersion(mid) == True
), it’s important to note thatmid
may not be the answer we’re looking for because we want to find the first bad version. In this case, we need to check if the version beforemid
(mid - 1
) is also a bad version. If it is, it means thatmid
is not the answer, so we move theright
pointer to the element beforemid
and repeat the above steps. On the other hand, if the version beforemid
is a normal version, it implies thatmid
is indeed the first bad version, so we can directly returnmid
.
- Calculate the midpoint
Codes
def first_bad_version(self, n: int) -> int:
left = 1
right = n
while left <= right:
mid = (left + right) // 2
if not isBadVersion(mid):
left = mid + 1
else:
if mid > 1 and isBadVersion(mid - 1):
right = mid - 1
else:
return mid
PythonComplexities
- Time Complexity:
O(logN)
, where N isn
. - Space Complexity:
O(1)
References
- LeetCode link: First Bad Version – LeetCode