Fruit Into Baskets
Keep one window [left … right] and a map count[type] of how many fruits of each type are inside. The number of keys in the map is the number of types. Grow the window on the right every step. If a third type appears, move left forward and drop fruits until one type's count reaches 0 and it is removed from the map. Then the window is valid again, and its length is a candidate answer.
The window is valid when it contains at most 2 distinct fruit types (count.size() ≤ 2). How many fruits of each type does not matter.
Problem
There is a row of fruit trees. fruits[i] is the type of fruit on tree i.
You have two baskets, and each basket can hold only one type of fruit (but as many fruits of that type as you like).
You pick a starting tree and walk right, picking exactly one fruit from every tree you pass. You must stop as soon as you reach a tree whose fruit fits in neither basket.
Return the most fruits you can pick.
In other words: find the longest contiguous subarray that contains at most 2 different values.
An integer array fruits, where fruits[i] is the type of fruit on tree i.
One integer: the length of the longest contiguous subarray with at most 2 distinct values.
Only 2 types (1 and 2), so you can pick from all three trees.
Start at tree 1 and pick [1, 2, 2]. Starting at tree 0 would stop at the third type (2) after only 2 fruits.
Pick [2, 3, 2, 2] starting from tree 1.
- • 1 ≤ fruits.length ≤ 10^5
- • 0 ≤ fruits[i] < fruits.length
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Do the picked trees have to be next to each other, or can I skip trees?
- 2.
What does "two baskets, one type each" really limit — the number of fruits, or the number of different types?
- 3.
If a block of trees is fine, is every smaller block inside it also fine?
- 4.
When a third type shows up, which trees could I stop picking from to make it fine again?
- 5.
What do I need to remember about the current block to know how many types it has?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | For each start, walk right until a third type appears | O(N²) | O(1) |
| Optimal | Grow right; while there are 3 types, shrink left until one type is gone | O(N) | O(1) |
Why does this belong to this pattern?
- “walk right from a starting tree, picking from every tree”The answer is a contiguous range [l … r] → think window.
- “maximum number of fruits”We want the longest valid range → variable window that grows on the right and shrinks on the left.
- “two baskets, one type each”At most 2 distinct values in the window → we need the counts of each value to know when a value fully leaves.
This is the anchor of the frequency-map family. The window rule depends on what is inside the window (how many distinct types), not on a sum. Learn the core moves here: add on the right, remove on the left, and delete a key when its count reaches 0 so that count.size() is the number of distinct types. The next questions keep the same loop and only change the rule: exactly k distinct (GFG K Uniques), length − maxFreq ≤ k (Character Replacement), every count ≤ k (LC 2958), or covering a target (Minimum Window).
Don't make this mistake
Fruit Into Baskets is NOT windowSize − maxFrequency ≤ 2; the condition is distinct types ≤ 2. windowSize − maxFreq counts how many fruits are not the most common type — that is the rule for Longest Repeating Character Replacement. Here, [1,2,1,2,1,2] is perfectly valid (2 types) even though 6 − 3 = 3 > 2.
count.size() counts keys, including keys with value 0. If you don't erase, a type that already left the window still counts as a basket, and the loop shrinks forever (or far too much).
Removing one fruit may not remove a whole type. In [3,3,3,1,2], when 2 arrives you must drop all three 3s before the window is valid again.
Some people reset left = right when a third type appears. That throws away the fruits of the type just before right, which can still be picked. For [1,2,1,1,3,1,1] the answer is 5 ([1,1,3,1,1]), but resetting to [3] gives only 4. Shrink one step at a time until a type disappears.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Sliding Window translate into production architectures and low-level memory mechanics.