Hello! Welcome back.
In our last lesson, you mastered linear and binary search for finding an element within a sorted array. We emphasized that binary search's O(log n) efficiency is a game-changer, but it requires the data to be sorted.
Today, we're going to elevate that concept. Instead of searching for an element in an array, we'll search for an optimal solution within a range of possibilities. This powerful technique, known as Binary Search on the Answer Space, is a cornerstone of competitive programming and a common pattern in technical interviews for solving optimization problems. You'll learn how to identify problems that fit this pattern, define the search space, and implement an efficient solution.
The Core Idea: Searching for an Answer, Not an Element
The magic of binary search works because of a predictable, ordered property. In a sorted array, if you're at mid and your target is smaller, you know for sure it's to the left.
We can apply the same logic to a range of potential answers to a problem, provided the problem has a monotonic property. A function is monotonic if it's consistently non-decreasing or non-increasing.

For many optimization problems, we can define a feasible(x) function that asks, "Is it possible to achieve a solution with value x?". This function often creates a monotonic sequence of False and True values. For example, if we want to find the minimum possible value that works, our feasibility function might look like this:
[False, False, False, ..., True, True, True]
Our goal becomes finding the first True in this implicit array of boolean values.

Let's formalize this.
Binary Search on Answer Tutorial with Problems
The article 'Binary Search on Answer' from GeeksForGeeks clearly explains how to identify problems that are suitable for this technique.
Please read the section 'How to identify Binary Search on answer'. It highlights the two key ingredients: a defined search space for the answer (L to R) and a monotonic relationship within that space.
Now, let's apply this powerful pattern to a classic problem.
Case Study 1: Koko Eating Bananas
This problem is a perfect, intuitive example of "minimizing a maximum" (or in this case, minimizing a rate). The goal is to find the minimum eating speed K that allows Koko to finish all bananas within a given time H.
Let's watch a detailed breakdown of the problem.
The 'take U forward' channel provides an excellent explanation of the 'Koko Eating Bananas' problem, which we will use as our first case study.
Watch from 00:17 to 05:24 to understand the problem statement, constraints, and the goal. Pay attention to how the time taken is calculated for a given eating speed (it's always the ceiling value).
Step 1: Defining the Search Space
Instead of searching the piles array, we'll search for the answer K (bananas per hour). What's the possible range for K?
low: The slowest possible speed is1banana per hour. Any slower doesn't make sense.high: The fastest Koko ever needs to eat is determined by the largest pile. If the largest pile isMbananas, an eating speed greater thanMprovides no additional benefit for that pile compared to a speed ofM(it still takes 1 hour). So, the maximum value in thepilesarray is a reasonable upper bound.
So, our answer K lies somewhere in the range [1, max(piles)].
Let's confirm this logic for establishing the search space.
Watch from 05:55 to 07:45. The video explains why the answer must lie between 1 and the maximum element in the array.
Step 2: The isPossible(speed) Check Function
This is the heart of the solution. We need a function that, for a given speed, tells us if it's possible to eat all bananas within H hours.
The logic is straightforward:
- Initialize
totalTime = 0. - Iterate through each pile
pin thepilesarray. - Calculate the time taken for that pile:
time = ceil((double)p / speed). In integer arithmetic, a clever way to compute the ceilingceil(a/b)is(a + b - 1) / b. - Add this time to
totalTime. - After checking all piles, if
totalTime <= H, returntrue. Otherwise, returnfalse.
Step 3: Applying Binary Search
Now we combine the search space and the check function.
- Initialize
low = 1,high = max(piles). - Initialize a variable
ansto store the best possible speed found so far. - Loop while
low <= high:- Calculate
mid = low + (high - low) / 2. - If
isPossible(mid)istrue:- This
midspeed works! It's a potential answer. - We want the minimum possible speed, so let's see if we can do even better (slower).
- Store this answer:
ans = mid. - Search the left half:
high = mid - 1.
- This
- If
isPossible(mid)isfalse:- This
midspeed is too slow. We need to eat faster. - Search the right half:
low = mid + 1.
- This
- Calculate
The final value in ans will be our answer.
Watch the full binary search logic applied to this problem.
Watch from 10:05 to 16:59. This section walks through the entire binary search process, showing how the low and high pointers are adjusted based on the feasibility check.
Code Implementation
Here's how this would look in Java:
public class KokoEatingBananas {
// Check function: is it possible to finish in H hours with a given speed?
public static boolean isPossible(int[] piles, int speed, int H) {
long totalTime = 0; // Use long to avoid overflow if piles are large
for (int p : piles) {
// Calculate time for this pile: ceil(p / speed)
totalTime += (p + speed - 1) / speed;
}
return totalTime <= H;
}
public static int minEatingSpeed(int[] piles, int H) {
int low = 1;
int high = 0;
for (int p : piles) {
high = Math.max(high, p);
}
int ans = high; // A valid speed is guaranteed to exist
while (low <= high) {
int mid = low + (high - low) / 2;
if (mid == 0) { // Avoid division by zero
low = 1;
continue;
}
if (isPossible(piles, mid, H)) {
ans = mid; // This is a possible answer, try for a smaller one
high = mid - 1;
} else {
low = mid + 1; // Speed is too slow, must increase
}
}
return ans;
}
}
The time complexity of isPossible is O(N) where N is the number of piles. We call this function O(log M) times, where M is the maximum value in the piles. The total time complexity is O(N * log M), a massive improvement over a brute-force linear scan.
Case Study 2: Allocate Books
Let's tackle a more complex problem that follows the same pattern: "minimize the maximum". The goal is to allocate books to a set number of students such that the maximum number of pages assigned to any single student is minimized.
BS-18. Allocate Books or Book Allocation | Hard Binary Search
The 'Allocate Books' problem is another classic. Let's start by understanding its rules and objective.
Watch from 00:16 to 05:50. Focus on the three conditions of allocation: every student gets a book, one book goes to one student, and allocations are contiguous. The goal is to minimize the max pages any student reads.
Step 1: Defining the Search Space
What is the range for our answer (the maximum number of pages a student can be assigned)?
low: The answer cannot be smaller than the largest book in the array. Even if a student gets only one book, they must be able to handle the largest one. So,low = max(array).high: In the worst/most generous allocation, one student gets all the books. So,high = sum(array).
Our answer lies in the range [max(array), sum(array)].
BS-18. Allocate Books or Book Allocation | Hard Binary Search
Let's see this search space explained in the video.
Watch from 17:40 to 19:49. This part clearly defines the lower and upper bounds for our binary search.
Step 2: The canAllocate(maxPages) Check Function
Given a potential answer maxPages (the maximum pages any student is allowed), can we allocate all books to M students?
We can determine this greedily:
- Initialize
studentsNeeded = 1andcurrentPages = 0. - Iterate through the books:
- For each book, if
currentPages + bookPages <= maxPages, add it to the current student's load:currentPages += bookPages. - If it exceeds the limit, the current student can't take this book. Give it to a new student: increment
studentsNeededand setcurrentPages = bookPages.
- For each book, if
- After iterating through all books, if
studentsNeeded <= M, it means the allocation is possible with the givenmaxPageslimit. Returntrue.
BS-18. Allocate Books or Book Allocation | Hard Binary Search
The implementation of this check function is the most critical part of the problem. Let's watch it being built.
Watch from 14:53 to 17:40. The video details the logic for the countStudents helper function, which is exactly our canAllocate check.
Test your understanding!
You have books with pages [10, 20, 30, 40] and 2 students. Your canAllocate check function is called with maxPages = 50. How many students will the function determine are needed? Will it return true or false?
Show answer
The function will determine that 2 students are needed, so it will return true.
- Student 1: Takes the 10-page book (
currentPages = 10). Takes the 20-page book (currentPages = 30). Takes the 30-page book? No,30 + 30 > 50. - Student 2: Takes the 30-page book (
currentPages = 30). Takes the 40-page book? No,30 + 40 > 50. - Student 3: Takes the 40-page book (
currentPages = 40).
Wait, that's 3 students. Let's re-read the logic.
- Student 1: Takes 10 (
current=10). Takes 20 (current=30). Tries to take 30, but30+30 > 50. So Student 1 gets[10, 20]. - Start Student 2: Takes 30 (
current=30). Tries to take 40, but30+40 > 50. So Student 2 gets[30]. - Start Student 3: Takes 40 (
current=40).
The logic was right, I miscalculated in my head. It requires 3 students. Since 3 > 2, canAllocate(50) would return false. The maximum pages allowed per student must be higher.
Step 3: Applying Binary Search
The binary search logic is nearly identical to the Koko problem:
- If
canAllocate(mid)istrue:- This
midvalue is a possible solution. We want to find an even smaller maximum. - Store the answer:
ans = mid. - Search the left half:
high = mid - 1.
- This
- If
canAllocate(mid)isfalse:- The
midlimit is too restrictive, we needed too many students. We must allow students to carry more pages. - Search the right half:
low = mid + 1.
- The
BS-18. Allocate Books or Book Allocation | Hard Binary Search
Finally, let's see the full binary search algorithm applied to the 'Allocate Books' problem.
Watch from 19:49 to 25:26 for a step-by-step walkthrough of how binary search narrows down the range of possible answers to find the optimal one.
The time complexity is O(N * log(S)), where N is the number of books and S is the sum of all pages (the size of our search space).
Conclusion
Today you've unlocked a powerful problem-solving paradigm. By reframing optimization problems, you can leverage the O(log n) efficiency of binary search in a much broader context than just searching in arrays. This is a huge step forward for your competitive programming and technical interview preparation.
Key Takeaways:
- Binary Search on the Answer is a technique for optimization problems, often identified by "minimize the maximum" or "maximize the minimum" phrasing.
- The core requirement is a monotonic
checkfunction that validates a potential answer. This creates a[False, ..., True, ...]pattern that binary search can exploit. - The three-step process is:
- Define the Search Space: Determine the absolute lowest and highest possible values for the answer.
- Implement a Check Function: Write a function
isPossible(value)that returnstrueorfalse. This function typically runs in linear time. - Apply Binary Search Template: Use the
checkfunction to guide the binary search in the defined search space, shrinking the range until you find the optimal value.
Preview of the next lesson:
We will now circle back to applying binary search on arrays, but with a twist. In the next lesson, you will learn to "Solve problems on rotated sorted arrays using a modified binary search." This is another classic interview problem that forces you to think critically about how binary search's core principles can be adapted when the array isn't perfectly sorted.