You are visiting a farm that has a single row of fruit trees arranged from left to right. The trees are represented by an integer array fruits where fruits[i] is the type of fruit the i-th tree produces.
You want to collect as much fruit as possible. However, the owner has some strict rules that you must follow:
Given the integer array fruits, return the maximum number of fruits you can pick.
Example 1:
Input: fruits = [1,2,1]
Output: 3Explanation: We can pick from all trees.
Example 2:
Input: fruits = [0,1,2,2]
Output: 3Explanation: We can pick from trees [1,2,2].
If we had started at the first tree, we would only pick from trees [0,1].
Example 3:
Input: fruits = [1,2,3,2,2]
Output: 4Explanation: We can pick from trees [2,3,2,2].
If we had started at the first tree, we would only pick from trees [1,2].
Constraints:
1 <= fruits.length <= 100,0000 <= fruits[i] < fruits.lengthBefore attempting this problem, you should be comfortable with:
This problem asks for the longest contiguous subarray containing at most two distinct values. We can check every possible starting position and extend as far as possible while keeping track of at most two fruit types.
For each starting index, we greedily expand until we encounter a third distinct type, then record the length.
i:types to track distinct fruit types.j from i while we have fewer than two types or the current fruit is already in our types set.j.j - i.Instead of restarting from each position, we maintain a sliding window that always contains at most two fruit types. When we encounter a third type, we shrink the window from the left until only two types remain.
A hash map tracks the count of each fruit type in the current window. When a count drops to zero, we remove that type from the map.
count, left pointer l = 0, and res = 0.r:fruits[r] to the count map.count[fruits[l]].l.res with the current window size.res.class Solution:
def totalFruit(self, fruits: List[int]) -> int:
count = defaultdict(int)
l, total, res = 0, 0, 0
for r in range(len(fruits)):
count[fruits[r]] += 1
total += 1
while len(count) > 2:
f = fruits[l]
count[f] -= 1
total -= 1
l += 1
if not count[f]:
count.pop(f)
res = max(res, total)
return resSimilar to the advanced sliding window for frequency problems, we only care about the maximum window size. Once we achieve a valid window of size w, we never need a smaller one.
When a third fruit type appears, instead of shrinking until valid, we just slide the window forward by one position. The window size only increases when we find valid configurations, and the final size equals our answer.
count and left pointer l = 0.r:fruits[r] to the count map.count[fruits[l]].l.n - l as the maximum window size.class Solution:
def totalFruit(self, fruits: List[int]) -> int:
count = defaultdict(int)
l = 0
for r in range(len(fruits)):
count[fruits[r]] += 1
if len(count) > 2:
count[fruits[l]] -= 1
if count[fruits[l]] == 0:
count.pop(fruits[l])
l += 1
return len(fruits) - lSince we only track two fruit types, we can avoid using a hash map entirely. Instead, we store the two fruit types and the last index where each appeared. When a third type appears, we can immediately jump the left pointer to just after the earlier of the two last indices.
This approach uses O(1) space and handles the window adjustment in constant time by directly computing where the new window should start.
fruit1, fruit2, and their last indices fruit1_lastIdx, fruit2_lastIdx.l = 0 and res = 1.r:fruits[r] matches fruit1, update fruit1_lastIdx.fruit2 (or fruit2 is unset), update accordingly.l to be one past that smaller index.res with r - l + 1.res.class Solution:
def totalFruit(self, fruits: list[int]) -> int:
l = 0
fruit1_lastIdx = 0
fruit2_lastIdx = -1
fruit1 = fruits[0]
fruit2 = -1
total = res = 1
for r in range(len(fruits)):
f = fruits[r]
if f == fruit1:
total += 1
fruit1_lastIdx = r
elif f == fruit2 or fruit2 == -1:
total += 1
fruit2_lastIdx = r
fruit2 = f
else:
if fruit2_lastIdx == min(fruit1_lastIdx, fruit2_lastIdx):
fruit1_lastIdx, fruit2_lastIdx = fruit2_lastIdx, fruit1_lastIdx
fruit1, fruit2 = fruit2, fruit1
total -= (fruit1_lastIdx - l + 1)
l = fruit1_lastIdx + 1
fruit1 = f
fruit1_lastIdx = r
res = max(res, r - l + 1)
return resWhen shrinking the window and decrementing fruit counts, forgetting to remove entries with count zero from the hash map causes the map size to incorrectly indicate more than two fruit types. Always check if a count becomes zero and remove that key from the map before checking the size constraint.
The window size is r - l + 1, not r - l. Forgetting the +1 leads to undercounting the maximum fruits by one. This is especially easy to miss in the advanced sliding window approach where the final answer is n - l, which correctly accounts for the inclusive nature of the window.
The problem asks for at most two distinct fruit types, not exactly two. Some solutions incorrectly handle the case where all fruits are the same type (only one type present). The window should still be valid when containing just one fruit type, so the condition should check count.size() > 2, not count.size() != 2.