LeetCode[#278]| First Bad Version | Explanation

Rohit Mundada
AlgoPosts
Published in
3 min readMay 11, 2020

Recently I have been taking part in the May LeetCode Challenge. And decided to come up with solutions of all the problems I solve and the thought process behind it.
Some of the problems might be easy and others quite unintuitive, nevertheless every problem made me learn something that I should document.

Let’s begin with it.

Question[Link]: 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 will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

Example:

Given n = 5, and version = 4 is the first bad version.call isBadVersion(3) -> false
call isBadVersion(5) -> true
call isBadVersion(4) -> true
Then 4 is the first bad version.

Explanation:

The expectations are pretty straightforward, we need to return the firsti which belongs to {1,2..n} and returns true for the function isBadVersion.

Brute Force (Trivial) approach:

The first intuitive thing we could do is to check for each number from {1,2..n}and return i as soon as isBadVersion(i)==true .

Time Complexity: O(n), we would check n numbers in worst case
Space Complexity: O(1)

Optimal approach:

Now, the reason that the above approach is returning us the first i is because {1,2..n} is a sorted(ascending) set of numbers. Let’s see if we can use the property of the numbers being sorted.

We represent isBadVersion(i) as f(i) from now on. The solution values for this function for {1,2..n} looks like this: {F, F,...F,T,T...T} and the series of false and trues only occur due to the ascending order of numbers.

So, if we randomly pick a value(i) from the solution set we can conclude whether numbers to the left of i will return false or true:

When a value returns false from isBadVersion(i)

We can conclude that all numbers less than i would return false, but cannot say anything about the values to the right of i

When a value returns true from isBadVersion(i)

We can conclude that all numbers greater than i would return true, but numbers less than i may or may not return false.

So we see, at each guess we can deduce whether our next guess should be from numbers to the right of i or left of i . So, for each i we take a decision to reduce the search space.

And when our search space reduces to just one element we get our answer.
This might give us a hint for using a binary search over the space, where our guess would be the middle element each time we reduce the search space.

Algorithm:

  1. select a mid element.
  2. if isBadVersion(mid)==false move the search space to right.
  3. if isBadVersion(mid)==true save mid; and move search space to left.
  4. get out of the loop when space converges to 1 element.

the code for this explain it better:

int low=1,high=n,mid;
int ans=-1;
while(low<=high)
{
mid = low + ((high - low)/2 );
if(isBadVersion(mid))
{
high=mid-1;
ans=mid;
}
else
low=mid+1;
}
return ans;

Hope the code explains it better.

To learn more about binary search basics : check Binary Search Tutorial, this article is really worth the time.

Time Complexity: O(log n) as search space reduces to half at every decision.
Space Complexity: O(1).

--

--