1196. How Many Apples Can You Put into the Basket π
Problem Description
You have a collection of apples and a basket that can hold a maximum weight of 5000
units.
You're given an integer array weight
where weight[i]
represents the weight of the i-th
apple. Your task is to determine the maximum number of apples you can put in the basket without exceeding its weight capacity.
For example, if you have apples with weights [100, 200, 150, 1000]
and your basket can carry up to 5000
units, you can put all 4 apples in the basket since their total weight is 1450
, which is less than 5000
.
The key insight is that to maximize the number of apples, you should prioritize lighter apples first. The solution sorts the apples by weight in ascending order and keeps adding them to the basket until adding another apple would exceed the 5000
unit limit. At that point, it returns the count of apples successfully added. If all apples fit within the weight limit, it returns the total number of apples.
Intuition
When faced with a constraint on total weight and the goal of maximizing count, a natural strategy emerges: prioritize the lightest items first. This is a classic greedy approach.
Think of it like packing for a trip with a weight limit on your luggage. If you want to bring as many items as possible, you'd pack your lightest items first - socks before shoes, t-shirts before jackets. The same principle applies here with apples.
By sorting the apples from lightest to heaviest, we ensure that we're always making the locally optimal choice at each step. Each time we add an apple to the basket, we're adding the lightest available apple, which leaves us with the maximum possible remaining capacity for future apples.
The beauty of this approach is that the local optimal choices lead to a global optimum. Why? Because if we were to swap any included light apple with an excluded heavier apple, we'd either exceed the weight limit or reduce the total count of apples we can carry.
The implementation becomes straightforward: sort the array, then iterate through it while keeping a running sum of weights. As soon as adding the next apple would exceed 5000
units, we stop and return the count. If we can add all apples without exceeding the limit, we return the total count.
This greedy strategy works because there's no benefit to choosing heavier apples over lighter ones when our only goal is to maximize quantity, not value or any other property.
Solution Approach
The implementation follows a straightforward greedy algorithm that consists of two main steps:
Step 1: Sort the weights
weight.sort()
We sort the weight
array in ascending order. This ensures we process apples from lightest to heaviest. Python's built-in sort()
method uses Timsort, which has a time complexity of O(n log n)
.
Step 2: Accumulate weights until limit is exceeded
s = 0
for i, x in enumerate(weight):
s += x
if s > 5000:
return i
return len(weight)
We iterate through the sorted array while maintaining a running sum s
of the weights added so far. The enumerate()
function gives us both the index i
and the weight value x
for each apple.
For each apple:
- Add its weight to the running sum
s
- Check if the total weight exceeds
5000
- If it does, return the current index
i
, which represents the number of apples we successfully added before this one - If we complete the loop without exceeding the limit, return
len(weight)
, meaning all apples fit in the basket
Time Complexity: O(n log n)
where n
is the number of apples, dominated by the sorting operation.
Space Complexity: O(1)
if we consider the sort operation to be in-place (though technically Python's sort uses O(n)
auxiliary space in the worst case).
The algorithm guarantees the maximum number of apples because by always choosing the lightest available apple, we minimize the weight added at each step, leaving maximum capacity for additional apples.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example with apples having weights [900, 950, 800, 1000, 700, 1800]
and our basket capacity of 5000
units.
Step 1: Sort the weights in ascending order
After sorting: [700, 800, 900, 950, 1000, 1800]
Step 2: Iterate through sorted weights, accumulating the sum
-
Iteration 0:
- Current apple weight:
700
- Running sum:
0 + 700 = 700
- Is
700 > 5000
? No, continue
- Current apple weight:
-
Iteration 1:
- Current apple weight:
800
- Running sum:
700 + 800 = 1500
- Is
1500 > 5000
? No, continue
- Current apple weight:
-
Iteration 2:
- Current apple weight:
900
- Running sum:
1500 + 900 = 2400
- Is
2400 > 5000
? No, continue
- Current apple weight:
-
Iteration 3:
- Current apple weight:
950
- Running sum:
2400 + 950 = 3350
- Is
3350 > 5000
? No, continue
- Current apple weight:
-
Iteration 4:
- Current apple weight:
1000
- Running sum:
3350 + 1000 = 4350
- Is
4350 > 5000
? No, continue
- Current apple weight:
-
Iteration 5:
- Current apple weight:
1800
- Running sum:
4350 + 1800 = 6150
- Is
6150 > 5000
? Yes! Return index5
- Current apple weight:
Result: We can fit 5
apples in the basket (all except the heaviest one weighing 1800
units).
By choosing the lightest apples first [700, 800, 900, 950, 1000]
, we maximized our count. If we had greedily picked the heavier apples first, we would have gotten fewer apples. For instance, picking [1800, 1000, 950, 900]
gives us only 4 apples with a total weight of 4650
, even though we had room for more weight.
Solution Implementation
1class Solution:
2 def maxNumberOfApples(self, weight: List[int]) -> int:
3 """
4 Find the maximum number of apples that can be carried with a weight limit of 5000 units.
5 Strategy: Greedy approach - take the lightest apples first to maximize count.
6
7 Args:
8 weight: List of integers representing the weight of each apple
9
10 Returns:
11 Maximum number of apples that can be carried without exceeding 5000 units
12 """
13 # Sort apples by weight in ascending order (lightest first)
14 weight.sort()
15
16 # Track cumulative weight
17 cumulative_weight = 0
18
19 # Iterate through sorted apples and accumulate weight
20 for index, apple_weight in enumerate(weight):
21 cumulative_weight += apple_weight
22
23 # If adding this apple exceeds the limit, return the count of apples taken so far
24 if cumulative_weight > 5000:
25 return index
26
27 # If all apples can be carried without exceeding the limit, return total count
28 return len(weight)
29
1class Solution {
2 public int maxNumberOfApples(int[] weight) {
3 // Sort the apple weights in ascending order to greedily pick the lightest apples first
4 Arrays.sort(weight);
5
6 // Initialize the total weight sum
7 int totalWeight = 0;
8
9 // Iterate through the sorted array of apple weights
10 for (int i = 0; i < weight.length; i++) {
11 // Add the current apple's weight to the total
12 totalWeight += weight[i];
13
14 // Check if adding this apple exceeds the weight limit of 5000 units
15 if (totalWeight > 5000) {
16 // Return the number of apples we could carry (current index)
17 return i;
18 }
19 }
20
21 // If we can carry all apples without exceeding the limit, return the total count
22 return weight.length;
23 }
24}
25
1class Solution {
2public:
3 int maxNumberOfApples(vector<int>& weight) {
4 // Sort the weights in ascending order to prioritize lighter apples
5 sort(weight.begin(), weight.end());
6
7 // Initialize the cumulative weight sum
8 int cumulativeWeight = 0;
9
10 // Iterate through the sorted weights
11 for (int i = 0; i < weight.size(); ++i) {
12 // Add the current apple's weight to the total
13 cumulativeWeight += weight[i];
14
15 // Check if the weight limit (5000 units) is exceeded
16 if (cumulativeWeight > 5000) {
17 // Return the number of apples that fit within the limit
18 return i;
19 }
20 }
21
22 // If all apples fit within the weight limit, return the total count
23 return weight.size();
24 }
25};
26
1/**
2 * Calculates the maximum number of apples that can be carried without exceeding 5000 units of weight
3 * @param weight - Array of integers representing the weight of each apple
4 * @returns The maximum number of apples that can be carried
5 */
6function maxNumberOfApples(weight: number[]): number {
7 // Sort the weight array in ascending order to greedily pick the lightest apples first
8 weight.sort((a: number, b: number) => a - b);
9
10 // Initialize the cumulative weight sum
11 let cumulativeWeight: number = 0;
12
13 // Iterate through the sorted weights
14 for (let i: number = 0; i < weight.length; ++i) {
15 // Add the current apple's weight to the cumulative sum
16 cumulativeWeight += weight[i];
17
18 // If adding this apple exceeds the weight limit of 5000
19 if (cumulativeWeight > 5000) {
20 // Return the number of apples we could carry (excluding the current one)
21 return i;
22 }
23 }
24
25 // If we can carry all apples without exceeding the limit, return the total count
26 return weight.length;
27}
28
Time and Space Complexity
The time complexity is O(n Γ log n)
, where n
is the number of apples. This is dominated by the sorting operation weight.sort()
, which uses Python's Timsort algorithm with O(n Γ log n)
time complexity in the average and worst cases. The subsequent iteration through the sorted array takes O(n)
time, but this is absorbed by the higher complexity of sorting.
The space complexity is O(log n)
. While the sorting is performed in-place (modifying the original array without creating a new one), Python's Timsort algorithm requires O(log n)
space for its internal recursion stack and temporary storage during the merge operations. The additional variables s
and i
only require O(1)
space, so the overall space complexity is determined by the sorting algorithm's requirements.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Integer Overflow in Running Sum
While Python handles arbitrary precision integers automatically, in other languages like Java or C++, accumulating weights could cause integer overflow if the sum exceeds the maximum integer value before checking against 5000.
Solution: Use appropriate data types (like long
in Java) or check for overflow before addition:
# Safe addition check (conceptual for languages with overflow) if cumulative_weight > 5000 - apple_weight: return index cumulative_weight += apple_weight
2. Modifying the Original Input Array
The sort()
method modifies the input array in-place, which might be unexpected behavior if the caller needs to preserve the original order of weights.
Solution: Create a copy of the array before sorting:
def maxNumberOfApples(self, weight: List[int]) -> int:
sorted_weight = sorted(weight) # Creates a new sorted list
# ... rest of the implementation
3. Off-by-One Error in Return Value
A common mistake is returning i + 1
when the weight limit is exceeded, thinking we need to count the apples included. However, since enumerate
starts from 0 and we return before adding the current apple, i
already represents the correct count.
Incorrect:
if cumulative_weight > 5000: return i + 1 # Wrong! This counts the apple that exceeded the limit
Correct:
if cumulative_weight > 5000: return i # Correct - returns count of apples before exceeding limit
4. Edge Case: Empty Array
If the input array is empty, the current solution correctly returns 0, but it's worth explicitly handling this case for clarity:
Solution:
if not weight: return 0
5. Assuming All Weights are Positive
The solution assumes all apple weights are positive. If negative or zero weights are possible, the greedy approach might not work correctly as negative weights would be selected first after sorting.
Solution: Add validation or filter out non-positive weights:
weight = [w for w in weight if w > 0] weight.sort()
Which of the tree traversal order can be used to obtain elements in a binary search tree in sorted order?
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Donβt Miss This!