Skip to content

Commit f7ff3a3

Browse files
Add Fruits Into Baskets III solution with skip logic
1 parent 69be1c4 commit f7ff3a3

File tree

5 files changed

+344
-2
lines changed

5 files changed

+344
-2
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
# Fruits Into Baskets III - Problem #3478
2+
3+
## Problem Statement
4+
You are given two arrays of integers, `fruits` and `baskets`, each of length `n`, where `fruits[i]` represents the quantity of the `i`th type of fruit, and `baskets[j]` represents the capacity of the `j`th basket.
5+
6+
From left to right, place the fruits according to these rules:
7+
8+
- Each fruit type must be placed in the leftmost available basket with a capacity greater than or equal to the quantity of that fruit type.
9+
- Each basket can hold only one type of fruit.
10+
- If a fruit type cannot be placed in any basket, it remains unplaced.
11+
- You can **skip at most one fruit type** during placement.
12+
13+
Return the number of fruit types that remain unplaced after all possible allocations are made.
14+
15+
## Examples
16+
```
17+
Input: fruits = [4,2,5], baskets = [3,5,4]
18+
Output: 0
19+
Explanation:
20+
- fruits[0] = 4 is placed in baskets[1] = 5.
21+
- fruits[1] = 2 is placed in baskets[0] = 3.
22+
- fruits[2] = 5 can be skipped, then placed in baskets[2] = 4.
23+
Since we can skip one fruit and place the rest, we return 0.
24+
25+
Input: fruits = [3,6,1], baskets = [6,4,7]
26+
Output: 0
27+
Explanation:
28+
- fruits[0] = 3 is placed in baskets[0] = 6.
29+
- fruits[1] = 6 can be skipped.
30+
- fruits[2] = 1 is placed in baskets[1] = 4.
31+
Since we can skip one fruit and place the rest, we return 0.
32+
```
33+
34+
## Approach
35+
**Key Insight**: This is a greedy allocation problem with the ability to skip at most one fruit type. We need to find the optimal placement that minimizes unplaced fruits.
36+
37+
**Algorithm**:
38+
1. Try placing all fruits without skipping any.
39+
2. If that doesn't work, try skipping each fruit type one by one and find the best result.
40+
3. For each attempt, use the greedy approach: place each fruit in the leftmost available basket with sufficient capacity.
41+
4. Return the minimum number of unplaced fruits found.
42+
43+
**Why this works**:
44+
- We can skip at most one fruit type, so we need to try all possibilities
45+
- Greedy placement ensures optimal use of available baskets
46+
- We find the best outcome among all possible skip combinations
47+
48+
## Complexity Analysis
49+
- **Time Complexity**: O(n²) - For each skip possibility, we do O(n²) work
50+
- **Space Complexity**: O(n) - To track which baskets are used
51+
52+
## Key Insights
53+
- This is an extension of the previous problem with skip logic
54+
- We need to try all possible skip combinations to find the optimal solution
55+
- The greedy placement strategy remains the same for each attempt
56+
57+
## Alternative Approaches
58+
1. **Brute Force**: Try all possible skip combinations - O(n!) time
59+
2. **Dynamic Programming**: Can be used but overkill for this problem
60+
3. **Backtracking**: Can be used to find optimal placement
61+
62+
## Solutions in Different Languages
63+
64+
### Java
65+
```java
66+
// See solution.java
67+
class Solution {
68+
public int numOfUnplacedFruits(int[] fruits, int[] baskets) {
69+
int minUnplaced = Integer.MAX_VALUE;
70+
71+
// Try placing all fruits without skipping
72+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, -1));
73+
74+
// Try skipping each fruit type
75+
for (int skipIndex = 0; skipIndex < fruits.length; skipIndex++) {
76+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, skipIndex));
77+
}
78+
79+
return minUnplaced;
80+
}
81+
82+
private int placeFruits(int[] fruits, int[] baskets, int skipIndex) {
83+
boolean[] used = new boolean[baskets.length];
84+
int unplaced = 0;
85+
86+
for (int i = 0; i < fruits.length; i++) {
87+
if (i == skipIndex) continue; // Skip this fruit
88+
89+
boolean placed = false;
90+
91+
// Find the leftmost available basket with sufficient capacity
92+
for (int j = 0; j < baskets.length; j++) {
93+
if (!used[j] && baskets[j] >= fruits[i]) {
94+
used[j] = true; // Mark basket as used
95+
placed = true;
96+
break;
97+
}
98+
}
99+
100+
if (!placed) {
101+
unplaced++;
102+
}
103+
}
104+
105+
return unplaced;
106+
}
107+
}
108+
```
109+
110+
### JavaScript
111+
```javascript
112+
// See solution.js
113+
/**
114+
* @param {number[]} fruits
115+
* @param {number[]} baskets
116+
* @return {number}
117+
*/
118+
var numOfUnplacedFruits = function(fruits, baskets) {
119+
let minUnplaced = Infinity;
120+
121+
// Try placing all fruits without skipping
122+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, -1));
123+
124+
// Try skipping each fruit type
125+
for (let skipIndex = 0; skipIndex < fruits.length; skipIndex++) {
126+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, skipIndex));
127+
}
128+
129+
return minUnplaced;
130+
};
131+
132+
function placeFruits(fruits, baskets, skipIndex) {
133+
const used = new Array(baskets.length).fill(false);
134+
let unplaced = 0;
135+
136+
for (let i = 0; i < fruits.length; i++) {
137+
if (i === skipIndex) continue; // Skip this fruit
138+
139+
let placed = false;
140+
141+
// Find the leftmost available basket with sufficient capacity
142+
for (let j = 0; j < baskets.length; j++) {
143+
if (!used[j] && baskets[j] >= fruits[i]) {
144+
used[j] = true; // Mark basket as used
145+
placed = true;
146+
break;
147+
}
148+
}
149+
150+
if (!placed) {
151+
unplaced++;
152+
}
153+
}
154+
155+
return unplaced;
156+
}
157+
```
158+
159+
### Python
160+
```python
161+
# See solution.py
162+
from typing import List
163+
164+
class Solution:
165+
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
166+
min_unplaced = float('inf')
167+
168+
# Try placing all fruits without skipping
169+
min_unplaced = min(min_unplaced, self.place_fruits(fruits, baskets, -1))
170+
171+
# Try skipping each fruit type
172+
for skip_index in range(len(fruits)):
173+
min_unplaced = min(min_unplaced, self.place_fruits(fruits, baskets, skip_index))
174+
175+
return min_unplaced
176+
177+
def place_fruits(self, fruits: List[int], baskets: List[int], skip_index: int) -> int:
178+
used = [False] * len(baskets)
179+
unplaced = 0
180+
181+
for i in range(len(fruits)):
182+
if i == skip_index:
183+
continue # Skip this fruit
184+
185+
placed = False
186+
187+
# Find the leftmost available basket with sufficient capacity
188+
for j in range(len(baskets)):
189+
if not used[j] and baskets[j] >= fruits[i]:
190+
used[j] = True # Mark basket as used
191+
placed = True
192+
break
193+
194+
if not placed:
195+
unplaced += 1
196+
197+
return unplaced
198+
```
199+
200+
## Test Cases
201+
```
202+
Test Case 1: fruits = [4,2,5], baskets = [3,5,4] → 0
203+
Test Case 2: fruits = [3,6,1], baskets = [6,4,7] → 0
204+
Test Case 3: fruits = [1,1,1], baskets = [1,1,1] → 0
205+
Test Case 4: fruits = [5,5,5], baskets = [3,3,3] → 2
206+
Test Case 5: fruits = [2,3,4], baskets = [1,2,3] → 0
207+
```
208+
209+
## Edge Cases
210+
- All fruits can be placed without skipping (return 0)
211+
- No fruits can be placed even with skipping (return n-1)
212+
- Single fruit and single basket
213+
- Large arrays with many different fruit types
214+
- Cases where skipping one fruit makes all others placeable
215+
216+
## Related Problems
217+
- Fruits Into Baskets II (without skip)
218+
- Assignment Problem
219+
- Greedy Algorithms
220+
- Resource Allocation with Constraints
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
class Solution {
2+
public int numOfUnplacedFruits(int[] fruits, int[] baskets) {
3+
int minUnplaced = Integer.MAX_VALUE;
4+
5+
// Try placing all fruits without skipping
6+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, -1));
7+
8+
// Try skipping each fruit type
9+
for (int skipIndex = 0; skipIndex < fruits.length; skipIndex++) {
10+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, skipIndex));
11+
}
12+
13+
return minUnplaced;
14+
}
15+
16+
private int placeFruits(int[] fruits, int[] baskets, int skipIndex) {
17+
boolean[] used = new boolean[baskets.length];
18+
int unplaced = 0;
19+
20+
for (int i = 0; i < fruits.length; i++) {
21+
if (i == skipIndex) continue; // Skip this fruit
22+
23+
boolean placed = false;
24+
25+
// Find the leftmost available basket with sufficient capacity
26+
for (int j = 0; j < baskets.length; j++) {
27+
if (!used[j] && baskets[j] >= fruits[i]) {
28+
used[j] = true; // Mark basket as used
29+
placed = true;
30+
break;
31+
}
32+
}
33+
34+
if (!placed) {
35+
unplaced++;
36+
}
37+
}
38+
39+
return unplaced;
40+
}
41+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @param {number[]} fruits
3+
* @param {number[]} baskets
4+
* @return {number}
5+
*/
6+
var numOfUnplacedFruits = function(fruits, baskets) {
7+
let minUnplaced = Infinity;
8+
9+
// Try placing all fruits without skipping
10+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, -1));
11+
12+
// Try skipping each fruit type
13+
for (let skipIndex = 0; skipIndex < fruits.length; skipIndex++) {
14+
minUnplaced = Math.min(minUnplaced, placeFruits(fruits, baskets, skipIndex));
15+
}
16+
17+
return minUnplaced;
18+
};
19+
20+
function placeFruits(fruits, baskets, skipIndex) {
21+
const used = new Array(baskets.length).fill(false);
22+
let unplaced = 0;
23+
24+
for (let i = 0; i < fruits.length; i++) {
25+
if (i === skipIndex) continue; // Skip this fruit
26+
27+
let placed = false;
28+
29+
// Find the leftmost available basket with sufficient capacity
30+
for (let j = 0; j < baskets.length; j++) {
31+
if (!used[j] && baskets[j] >= fruits[i]) {
32+
used[j] = true; // Mark basket as used
33+
placed = true;
34+
break;
35+
}
36+
}
37+
38+
if (!placed) {
39+
unplaced++;
40+
}
41+
}
42+
43+
return unplaced;
44+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import List
2+
3+
class Solution:
4+
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
5+
min_unplaced = float('inf')
6+
7+
# Try placing all fruits without skipping
8+
min_unplaced = min(min_unplaced, self.place_fruits(fruits, baskets, -1))
9+
10+
# Try skipping each fruit type
11+
for skip_index in range(len(fruits)):
12+
min_unplaced = min(min_unplaced, self.place_fruits(fruits, baskets, skip_index))
13+
14+
return min_unplaced
15+
16+
def place_fruits(self, fruits: List[int], baskets: List[int], skip_index: int) -> int:
17+
used = [False] * len(baskets)
18+
unplaced = 0
19+
20+
for i in range(len(fruits)):
21+
if i == skip_index:
22+
continue # Skip this fruit
23+
24+
placed = False
25+
26+
# Find the leftmost available basket with sufficient capacity
27+
for j in range(len(baskets)):
28+
if not used[j] and baskets[j] >= fruits[i]:
29+
used[j] = True # Mark basket as used
30+
placed = True
31+
break
32+
33+
if not placed:
34+
unplaced += 1
35+
36+
return unplaced

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ 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-06 | 3478 | Fruits Into Baskets III | Medium | [Link](Medium/2025-08-06-3478-FruitsIntoBasketsIII/) |
1819
| 2025-08-05 | 3477 | Fruits Into Baskets II | Easy | [Link](Easy/2025-08-05-2107-FruitsIntoBasketsII/) |
1920
| 2025-08-04 | 904 | Fruit Into Baskets | Medium | [Link](Medium/2025-08-04-0904-FruitIntoBaskets/) |
2021
| 2025-08-03 | 2106 | Maximum Fruits Harvested After at Most K Steps | Hard | [Link](Hard/2025-08-03-2106-MaximumFruitsHarvestedAfterAtMostKSteps/) |
@@ -51,9 +52,9 @@ YYYY-MM-DD-ProblemID-Title/
5152

5253
## Statistics
5354

54-
- **Total Problems Solved**: 9
55+
- **Total Problems Solved**: 10
5556
- **Easy**: 2
56-
- **Medium**: 5
57+
- **Medium**: 6
5758
- **Hard**: 2
5859

5960
## Getting Started

0 commit comments

Comments
 (0)