The Power of Binary Search, or solving Leetcode Hards with a lil search
Binary search is quite easy to understand conceptually, you split the search space into two halves and only keep the half which has the target in it and throw away the other half.
But when it comes to implementation, it is rather difficult to write a bug-free binary search in just a few minutes. Some of the most important questions we ask are:
- When do we exit the loop? Should we use
left < right
orleft <= right
in the loop? - How do we initialise the boundary variables
left
andright
? - How do we update the boundaries? Do we use
left = mid
orleft = mid + 1
?
When I first studied binary search in university I thought binary search could only be used to find simple values in arrays (I also thought that you ate oranges with the skin on them, we live and we learn 🍊)
However, binary search can be applied to many Leetcode hard problems and is extremely useful.
Generalised Binary Search
Suppose we have a search space (whether it be an array, a range of numbers) thats sorted in ascending order.
The following code is the most generalised version of binary search across this search space:
def binary_search(array) -> int:
def condition(value) -> bool:
# The condition depends on what the question is asking us, this should pass True if it is what we're looking for
pass
left, right = min(search_space), max(search_space) # Left and right depends on the question. It could be [0, n] or [1, n]
while left < right:
# We do left < right here for a generalised form, we might want an <= depending on the question. Will talk morea bout it later
mid = left + (right - left) // 2
if condition(mid):
right = mid
else:
left = mid + 1
return left
With this template, for most problems, we only really need to modify three parts after copying and pasting it and we never need to worry about corner cases and bugs in code.
- Correctly initialise the boundary values
left
andright
to specify search space. We need to set up the boundary to include all possible elements. - Decide our return value. Do we
return left
orreturn left - 1
? After exiting the loop,left
is the minimalk
satisfying thecondition
. - We need to design the
condition
function. This is the most difficult part and the one you will practice the most ⚒️
Lets run through some simple binary search problems.
First Bad Version
This is a Leetcode easy problem solvable with binary search:
69.Sqrt(x)
35.Search Insert Position
Advanced Applications
The above problems are easy to solve because we are given the search space already and asked to search it.
For more advanced applications we may not even realise we can use Binary Search. Generally if we can discover some kind of statement like if condition(k) is True then condition(k+1) is True
then we can consider Binary Search.