Fruit Into Baskets
Master this topic with zero to advance depth.
Fruit Into Baskets
You are visiting a farm that has a single row of fruit trees. Each tree has a type. You have TWO baskets, each holding ONE type. Find the maximum fruits you can collect in a contiguous range.
Visual Representation
fruits = [1, 2, 1, 2, 3]
L R
| |
1, 2, 1, 2, 3 Types: {1, 2}, Count: 4
[---------]
L R
| |
1, 2, 1, 2, 3 Types: {2, 3}, Count: 2
[-]Examples
Level I: Brute Force
Intuition
Check every possible contiguous range of trees and count how many fruits and types are in that range. If the number of types is ≤ 2, the range is valid. Track the maximum fruits collected.
Thought Process
- Use two nested loops to define all possible ranges
[i, j]. - In the inner loop, add each fruit to a set to count types.
- If types ≤ 2, update
maxFruits = max(maxFruits, j - i + 1). - If types > 2, break the inner loop.
Detailed Dry Run
| i | j | fruits[j] | Types | Fruits | Max |
|---|---|---|---|---|---|
| 0 | 0 | 1 | {1} | 1 | 1 |
| 0 | 1 | 2 | {1, 2} | 2 | 2 |
| 0 | 2 | 1 | {1, 2} | 3 | 3 |
| 0 | 3 | 2 | {1, 2} | 4 | 4 |
| 0 | 4 | 3 | {1, 2, 3} | 5 | 4 (Break) |
Level II: Binary Search on Answer (O(N log N))
Intuition
We can binary search for the maximum number of fruits L we can collect. For a fixed length L, we check if any contiguous subarray of length L contains at most 2 distinct fruit types using a fixed-size sliding window.
Thought Process
- Search range is
[1, n]. - For a fixed
midlength:- Slide a window of size
mid. - Maintain a frequency map of fruit types in the window.
- If
map.size() <= 2at any point, the lengthmidis possible.
- Slide a window of size
- Adjust the search range based on possibility.
Pattern: BS on Answer + Sliding Window Check
Level III: Optimal (Sliding Window)
Intuition
Thought Process
We need to find the longest subarray that contains exactly or at most two distinct elements. We use a frequency map to track the fruits in our window. When the number of types (map size) exceeds 2, we shrink the window from the left.
Pattern: Variable Size Sliding Window (K Distinct Elements)
- Expand:
count[fruits[right]]++ - Constraint:
count.size() > 2 - Shrink:
while (count.size() > 2) { count[fruits[left]]--; if (count[fruits[left]] == 0) count.remove(fruits[left]); left++; }
Detailed Dry Run
| R | Fruit | Map | Map Size | Action | Result |
|---|---|---|---|---|---|
| 0 | 1 | {1:1} | 1 | Expand | 1 |
| 1 | 2 | {1:1, 2:1} | 2 | Expand | 2 |
| 2 | 1 | {1:2, 2:1} | 2 | Expand | 3 |
| 3 | 2 | {1:2, 2:2} | 2 | Expand | 4 |
| 4 | 3 | {1:2, 2:2, 3:1} | 3 | Shrink L (remove 1s) | 4 |
⚠️ Common Pitfalls & Tips
Be careful with shrinking: ensure you decrement the count and remove the key from the map ONLY when the count reaches zero. Forgetting to remove the key will result in an incorrect count.size().
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.