LeetCode 278: First Bad Version

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

  1. The most intuitive and basic solution is to iterate from version 1 to version n sequentially and check one by one. If isBadVersion returns True, 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
Python

Complexities

  • Time Complexity: O(N), where N is n.
  • 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

  1. Use two pointers, left and right, to represent the left and right boundaries of the current search range.
  2. When left is less than or equal to right:
    1. Calculate the midpoint mid of the current range as mid = (left + right) // 2.
    2. Check the version pointed to by mid. If it is a normal version (isBadVersion(mid) == False), it means that all versions before mid are also normal and can be skipped. Move the left pointer to the element immediately after mid.
    3. If mid points to a bad version (isBadVersion(mid) == True), it’s important to note that mid 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 before mid (mid - 1) is also a bad version. If it is, it means that mid is not the answer, so we move the right pointer to the element before mid and repeat the above steps. On the other hand, if the version before mid is a normal version, it implies that mid is indeed the first bad version, so we can directly return mid.

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
Python

Complexities

  • Time Complexity: O(logN), where N is n.
  • Space Complexity: O(1)

References

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

Table of Contents

Related Posts

LeetCode 657: Robot Return to Origin

There is a robot starting at the position (0, 0), the origin, on a 2D plane. Given a sequence of its moves, judge if this robot ends up at (0, 0) after it completes its moves.

You are given a

LeetCode 136: Single Number

Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.

You must implement a solution with a linear runtime complexity and use only constant extra space.

LeetCode 200: Number of Islands

Given an m x n 2D binary grid grid which represents a map of ‘1’s (land) and ‘0’s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically.