Skip to content

Commit eb950db

Browse files
Add Fruit Into Baskets solution and update README with all recent problems
1 parent a3bf3f1 commit eb950db

File tree

5 files changed

+255
-6
lines changed

5 files changed

+255
-6
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# Fruit Into Baskets - Problem #904
2+
3+
## Problem Statement
4+
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.
5+
6+
You want to collect as much fruit as possible. However, the owner has some strict rules that you must follow:
7+
8+
- You only have **two baskets**, and each basket can only hold a **single type** of fruit. There is no limit on the amount of fruit each basket can hold.
9+
- Starting from any tree, you must pick **exactly one fruit** from **every** tree (including the start tree) while moving to the right. The picked fruits must fit in one of your baskets.
10+
- Once you reach a tree with fruit that cannot fit in your baskets, you must stop.
11+
12+
Given the integer array `fruits`, return the **maximum number of fruits** you can pick.
13+
14+
## Examples
15+
```
16+
Input: fruits = [1,2,1]
17+
Output: 3
18+
Explanation: We can pick from all 3 trees.
19+
20+
Input: fruits = [0,1,2,2]
21+
Output: 3
22+
Explanation: We can pick from trees [1,2,2].
23+
If we started at the first tree, we would only pick from trees [0,1,2].
24+
25+
Input: fruits = [1,2,3,2,2]
26+
Output: 4
27+
Explanation: We can pick from trees [2,3,2,2].
28+
If we started at the first tree, we would only pick from trees [1,2,3,2,2].
29+
```
30+
31+
## Approach
32+
**Key Insight**: This is a classic sliding window problem where we need to find the longest subarray containing at most 2 different types of fruits.
33+
34+
**Algorithm**:
35+
1. Use a sliding window with two pointers (left and right).
36+
2. Use a HashMap to track the count of each fruit type in the current window.
37+
3. Expand the window by moving the right pointer and add fruits to the map.
38+
4. When the window contains more than 2 fruit types, shrink it from the left until it contains at most 2 types.
39+
5. Keep track of the maximum window size found.
40+
41+
**Why this works**:
42+
- We need to find the longest contiguous sequence with at most 2 different fruit types
43+
- Sliding window efficiently maintains the constraint of at most 2 types
44+
- The maximum window size gives us the answer
45+
46+
## Complexity Analysis
47+
- **Time Complexity**: O(n) - Each element is visited at most twice (once by right pointer, once by left pointer)
48+
- **Space Complexity**: O(1) - HashMap will contain at most 2 entries
49+
50+
## Key Insights
51+
- This is essentially finding the longest subarray with at most 2 distinct elements
52+
- Sliding window is the optimal approach for this type of problem
53+
- We can use HashMap to efficiently track fruit type counts
54+
55+
## Alternative Approaches
56+
1. **Brute Force**: Try all possible subarrays - O(n²) time
57+
2. **Two Pointers**: Similar to sliding window but less efficient
58+
3. **Dynamic Programming**: Can be used but overkill for this problem
59+
60+
## Solutions in Different Languages
61+
62+
### Java
63+
```java
64+
// See solution.java
65+
import java.util.*;
66+
67+
class Solution {
68+
public int totalFruit(int[] fruits) {
69+
Map<Integer, Integer> basket = new HashMap<>();
70+
int left = 0;
71+
int maxFruits = 0;
72+
73+
for (int right = 0; right < fruits.length; right++) {
74+
basket.put(fruits[right], basket.getOrDefault(fruits[right], 0) + 1);
75+
76+
// Shrink window if we have more than 2 types
77+
while (basket.size() > 2) {
78+
basket.put(fruits[left], basket.get(fruits[left]) - 1);
79+
if (basket.get(fruits[left]) == 0) {
80+
basket.remove(fruits[left]);
81+
}
82+
left++;
83+
}
84+
85+
maxFruits = Math.max(maxFruits, right - left + 1);
86+
}
87+
88+
return maxFruits;
89+
}
90+
}
91+
```
92+
93+
### JavaScript
94+
```javascript
95+
// See solution.js
96+
/**
97+
* @param {number[]} fruits
98+
* @return {number}
99+
*/
100+
var totalFruit = function(fruits) {
101+
const basket = new Map();
102+
let left = 0;
103+
let maxFruits = 0;
104+
105+
for (let right = 0; right < fruits.length; right++) {
106+
basket.set(fruits[right], (basket.get(fruits[right]) || 0) + 1);
107+
108+
// Shrink window if we have more than 2 types
109+
while (basket.size > 2) {
110+
basket.set(fruits[left], basket.get(fruits[left]) - 1);
111+
if (basket.get(fruits[left]) === 0) {
112+
basket.delete(fruits[left]);
113+
}
114+
left++;
115+
}
116+
117+
maxFruits = Math.max(maxFruits, right - left + 1);
118+
}
119+
120+
return maxFruits;
121+
};
122+
```
123+
124+
### Python
125+
```python
126+
# See solution.py
127+
from typing import List
128+
from collections import defaultdict
129+
130+
class Solution:
131+
def totalFruit(self, fruits: List[int]) -> int:
132+
basket = defaultdict(int)
133+
left = 0
134+
max_fruits = 0
135+
136+
for right in range(len(fruits)):
137+
basket[fruits[right]] += 1
138+
139+
# Shrink window if we have more than 2 types
140+
while len(basket) > 2:
141+
basket[fruits[left]] -= 1
142+
if basket[fruits[left]] == 0:
143+
del basket[fruits[left]]
144+
left += 1
145+
146+
max_fruits = max(max_fruits, right - left + 1)
147+
148+
return max_fruits
149+
```
150+
151+
## Test Cases
152+
```
153+
Test Case 1: [1,2,1] → 3
154+
Test Case 2: [0,1,2,2] → 3
155+
Test Case 3: [1,2,3,2,2] → 4
156+
Test Case 4: [3,3,3,1,2,1,1,2,3,3,4] → 5
157+
Test Case 5: [1,1,1,1] → 4
158+
```
159+
160+
## Edge Cases
161+
- All fruits are the same type
162+
- Only one fruit type
163+
- Empty array
164+
- Large arrays with many different fruit types
165+
166+
## Related Problems
167+
- Longest Substring Without Repeating Characters
168+
- Longest Substring with At Most K Distinct Characters
169+
- Minimum Window Substring
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import java.util.*;
2+
3+
class Solution {
4+
public int totalFruit(int[] fruits) {
5+
Map<Integer, Integer> basket = new HashMap<>();
6+
int left = 0;
7+
int maxFruits = 0;
8+
9+
for (int right = 0; right < fruits.length; right++) {
10+
basket.put(fruits[right], basket.getOrDefault(fruits[right], 0) + 1);
11+
12+
// Shrink window if we have more than 2 types
13+
while (basket.size() > 2) {
14+
basket.put(fruits[left], basket.get(fruits[left]) - 1);
15+
if (basket.get(fruits[left]) == 0) {
16+
basket.remove(fruits[left]);
17+
}
18+
left++;
19+
}
20+
21+
maxFruits = Math.max(maxFruits, right - left + 1);
22+
}
23+
24+
return maxFruits;
25+
}
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @param {number[]} fruits
3+
* @return {number}
4+
*/
5+
var totalFruit = function(fruits) {
6+
const basket = new Map();
7+
let left = 0;
8+
let maxFruits = 0;
9+
10+
for (let right = 0; right < fruits.length; right++) {
11+
basket.set(fruits[right], (basket.get(fruits[right]) || 0) + 1);
12+
13+
// Shrink window if we have more than 2 types
14+
while (basket.size > 2) {
15+
basket.set(fruits[left], basket.get(fruits[left]) - 1);
16+
if (basket.get(fruits[left]) === 0) {
17+
basket.delete(fruits[left]);
18+
}
19+
left++;
20+
}
21+
22+
maxFruits = Math.max(maxFruits, right - left + 1);
23+
}
24+
25+
return maxFruits;
26+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from typing import List
2+
from collections import defaultdict
3+
4+
class Solution:
5+
def totalFruit(self, fruits: List[int]) -> int:
6+
basket = defaultdict(int)
7+
left = 0
8+
max_fruits = 0
9+
10+
for right in range(len(fruits)):
11+
basket[fruits[right]] += 1
12+
13+
# Shrink window if we have more than 2 types
14+
while len(basket) > 2:
15+
basket[fruits[left]] -= 1
16+
if basket[fruits[left]] == 0:
17+
del basket[fruits[left]]
18+
left += 1
19+
20+
max_fruits = max(max_fruits, right - left + 1)
21+
22+
return max_fruits

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ This repository is created for learning and educational purposes. The goal is to
1515

1616
| Date | Problem ID | Problem Title | Difficulty | Folder Link |
1717
|------|------------|---------------|------------|-------------|
18+
| 2025-08-04 | 904 | Fruit Into Baskets | Medium | [Link](Medium/2025-08-04-0904-FruitIntoBaskets/) |
19+
| 2025-08-03 | 2106 | Maximum Fruits Harvested After at Most K Steps | Hard | [Link](Hard/2025-08-03-2106-MaximumFruitsHarvestedAfterAtMostKSteps/) |
20+
| 2025-08-02 | 2857 | Rearranging Fruits | Hard | [Link](Hard/2025-08-02-2857-RearrangingFruits/) |
21+
| 2025-08-01 | 118 | Pascal's Triangle | Easy | [Link](Easy/2025-08-01-0118-PascalsTriangle/) |
22+
| 2025-07-31 | 898 | Bitwise ORs of Subarrays | Medium | [Link](Medium/2025-07-31-898-BitwiseORsOfSubarrays/) |
1823
| 2025-07-30 | 2412 | Longest Subarray with Maximum Bitwise AND | Medium | [Link](Medium/2025-07-30-2412-LongestSubarrayWithMaximumBitwiseAnd/) |
1924
| 2025-07-29 | 2411 | Smallest Subarrays With Maximum Bitwise OR | Medium | [Link](Medium/2025-07-29-2411-SmallestSubarraysWithMaximumBitwiseOR/) |
2025
| 2025-07-29 | 2044 | Count Number of Maximum Bitwise OR Subsets | Medium | [Link](Medium/2025-07-29-2044-CountNumberOfMaximumBitwiseORSubsets/) |
@@ -39,20 +44,21 @@ Each problem folder follows the structure:
3944
YYYY-MM-DD-ProblemID-Title/
4045
├── solution.java # Java solution code
4146
├── solution.js # JavaScript solution code
47+
├── solution.py # Python solution code
4248
└── explanation.md # Problem statement, approach, complexities
4349
```
4450

4551
## Statistics
4652

47-
- **Total Problems Solved**: 3
48-
- **Easy**: 0
49-
- **Medium**: 3
50-
- **Hard**: 0
53+
- **Total Problems Solved**: 8
54+
- **Easy**: 1
55+
- **Medium**: 5
56+
- **Hard**: 2
5157

5258
## Getting Started
5359

5460
1. Create a new problem folder using the format: `YYYY-MM-DD-ProblemID-Title`
55-
2. Add your solution code in `solution.java` and `solution.js`
61+
2. Add your solution code in `solution.java`, `solution.js`, and `solution.py`
5662
3. Document your approach in `explanation.md`
5763
4. Update this README with the new problem entry
5864

@@ -65,7 +71,7 @@ Each problem includes:
6571
- **Complexity Analysis**: Time and space complexity breakdown
6672
- **Key Insights**: Important observations and learning points
6773
- **Alternative Approaches**: Other possible solution methods
68-
- **Multi-language Solutions**: Implementations in Java and JavaScript
74+
- **Multi-language Solutions**: Implementations in Java, JavaScript, and Python
6975

7076
## Learning Objectives
7177

0 commit comments

Comments
 (0)