🧠
Sliding Window with Hash Map (Optimal)
💡 This approach uses a variable-size sliding window to efficiently track at most two distinct fruit types, making it much faster than brute force.
Intuition
Expand the window by moving the right pointer and track fruit counts. If more than two types appear, shrink the window from the left until only two types remain.
Algorithm
- Initialize two pointers left and right at 0, and a hashmap to count fruit types.
- Expand right pointer, add fruits[right] to hashmap.
- If hashmap size exceeds 2, move left pointer forward, decrementing counts, removing fruit types with zero count.
- Track the maximum window size where hashmap size ≤ 2.
- Return the maximum window size found.
💡 The key is maintaining the window so it always contains at most two distinct fruit types, which requires careful incrementing and decrementing counts.
def totalFruit(fruits):
basket = {}
left = 0
max_length = 0
for right in range(len(fruits)):
basket[fruits[right]] = basket.get(fruits[right], 0) + 1
while len(basket) > 2:
basket[fruits[left]] -= 1
if basket[fruits[left]] == 0:
del basket[fruits[left]]
left += 1
max_length = max(max_length, right - left + 1)
return max_length
# Driver code
if __name__ == '__main__':
print(totalFruit([1,2,1])) # Output: 3
print(totalFruit([0,1,2,2])) # Output: 3
print(totalFruit([1,2,3,2,2])) # Output: 4
Line Notes
basket = {}Initialize hashmap to count fruit types in current window
left = 0Left pointer starts at beginning of window
for right in range(len(fruits))Right pointer expands window to the right
basket[fruits[right]] = basket.get(fruits[right], 0) + 1Add current fruit to basket or increment count
while len(basket) > 2:If more than two fruit types, shrink window from left
basket[fruits[left]] -= 1Decrement count of fruit at left pointer
if basket[fruits[left]] == 0:Remove fruit type if count reaches zero
left += 1Move left pointer forward to shrink window
max_length = max(max_length, right - left + 1)Update max length if current window valid
return max_lengthReturn the longest valid window length
import java.util.*;
public class Solution {
public static int totalFruit(int[] fruits) {
Map<Integer, Integer> basket = new HashMap<>();
int left = 0, maxLength = 0;
for (int right = 0; right < fruits.length; right++) {
basket.put(fruits[right], basket.getOrDefault(fruits[right], 0) + 1);
while (basket.size() > 2) {
basket.put(fruits[left], basket.get(fruits[left]) - 1);
if (basket.get(fruits[left]) == 0) {
basket.remove(fruits[left]);
}
left++;
}
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
public static void main(String[] args) {
System.out.println(totalFruit(new int[]{1,2,1})); // 3
System.out.println(totalFruit(new int[]{0,1,2,2})); // 3
System.out.println(totalFruit(new int[]{1,2,3,2,2})); // 4
}
}
Line Notes
Map<Integer, Integer> basket = new HashMap<>();Initialize map to count fruit types in current window
int left = 0, maxLength = 0;Left pointer and max length initialization
for (int right = 0; right < fruits.length; right++) {Right pointer expands window
basket.put(fruits[right], basket.getOrDefault(fruits[right], 0) + 1);Add or increment fruit count
while (basket.size() > 2) {Shrink window if more than two fruit types
basket.put(fruits[left], basket.get(fruits[left]) - 1);Decrement count of fruit at left
if (basket.get(fruits[left]) == 0) {Remove fruit type if count zero
left++;Move left pointer forward
maxLength = Math.max(maxLength, right - left + 1);Update max length if current window valid
return maxLength;Return longest valid window length
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
int totalFruit(vector<int>& fruits) {
unordered_map<int, int> basket;
int left = 0, maxLength = 0;
for (int right = 0; right < (int)fruits.size(); right++) {
basket[fruits[right]]++;
while ((int)basket.size() > 2) {
basket[fruits[left]]--;
if (basket[fruits[left]] == 0) {
basket.erase(fruits[left]);
}
left++;
}
maxLength = max(maxLength, right - left + 1);
}
return maxLength;
}
int main() {
vector<int> fruits1 = {1,2,1};
cout << totalFruit(fruits1) << endl; // 3
vector<int> fruits2 = {0,1,2,2};
cout << totalFruit(fruits2) << endl; // 3
vector<int> fruits3 = {1,2,3,2,2};
cout << totalFruit(fruits3) << endl; // 4
return 0;
}
Line Notes
unordered_map<int, int> basket;Map to count fruit types in current window
int left = 0, maxLength = 0;Initialize left pointer and max length
for (int right = 0; right < (int)fruits.size(); right++) {Right pointer expands window
basket[fruits[right]]++;Add or increment fruit count
while ((int)basket.size() > 2) {Shrink window if more than two fruit types
basket[fruits[left]]--;Decrement count of fruit at left
if (basket[fruits[left]] == 0) {Remove fruit type if count zero
left++;Move left pointer forward
maxLength = max(maxLength, right - left + 1);Update max length if current window valid
return maxLength;Return longest valid window length
function totalFruit(fruits) {
const basket = new Map();
let left = 0, maxLength = 0;
for (let right = 0; right < fruits.length; right++) {
basket.set(fruits[right], (basket.get(fruits[right]) || 0) + 1);
while (basket.size > 2) {
basket.set(fruits[left], basket.get(fruits[left]) - 1);
if (basket.get(fruits[left]) === 0) {
basket.delete(fruits[left]);
}
left++;
}
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}
// Test cases
console.log(totalFruit([1,2,1])); // 3
console.log(totalFruit([0,1,2,2])); // 3
console.log(totalFruit([1,2,3,2,2])); // 4
Line Notes
const basket = new Map();Map to count fruit types in current window
let left = 0, maxLength = 0;Initialize left pointer and max length
for (let right = 0; right < fruits.length; right++) {Right pointer expands window
basket.set(fruits[right], (basket.get(fruits[right]) || 0) + 1);Add or increment fruit count
while (basket.size > 2) {Shrink window if more than two fruit types
basket.set(fruits[left], basket.get(fruits[left]) - 1);Decrement count of fruit at left
if (basket.get(fruits[left]) === 0) {Remove fruit type if count zero
left++;Move left pointer forward
maxLength = Math.max(maxLength, right - left + 1);Update max length if current window valid
return maxLength;Return longest valid window length
Each element is visited at most twice (once when right pointer moves forward, once when left pointer moves forward). The hashmap size is at most 3 during shrinking, so operations are O(1).
💡 For n=100000, this means roughly 200000 operations, which is efficient and runs comfortably within time limits.
Interview Verdict: Accepted
This is the optimal approach and what interviewers expect for this problem.