# Apple Redistribution into Boxes
**Difficulty:** EASY
[External](https://leetcode.com/problems/apple-redistribution-into-boxes)
Canonical: https://scaleengineer.com/dsa/problems/apple-redistribution-into-boxes
**Patterns:** [Greedy](https://scaleengineer.com/dsa/patterns/greedy)
**Algorithms:** [Sorting](https://scaleengineer.com/algorithms/sorting)
**Data structures:** Array
---
## Problem
You are given an array `apple` of size `n` and an array `capacity` of size `m`.

There are `n` packs where the `ith` pack contains `apple[i]` apples. There are `m` boxes as well, and the `ith` box has a capacity of `capacity[i]` apples.

Return _the **minimum** number of boxes you need to select to redistribute these_ `n` _packs of apples into boxes_.

**Note** that, apples from the same pack can be distributed into different boxes.

**Example 1:**

**Input:** apple = [1,3,2], capacity = [4,3,1,5,2]
**Output:** 2
**Explanation:** We will use boxes with capacities 4 and 5.
It is possible to distribute the apples as the total capacity is greater than or equal to the total number of apples.

**Example 2:**

**Input:** apple = [5,5,5], capacity = [2,4,2,7]
**Output:** 4
**Explanation:** We will need to use all the boxes.

**Constraints:**

* `1 <= n == apple.length <= 50`
* `1 <= m == capacity.length <= 50`
* `1 <= apple[i], capacity[i] <= 50`
* The input is generated such that it's possible to redistribute packs of apples into boxes.

# Approaches
## Greedy Approach with Sorting
The core idea is to first determine the total number of apples that need to be stored. Since apples from a single pack can be split among multiple boxes, we only need the sum of all apples. To use the minimum number of boxes, we should greedily pick the boxes with the largest capacities first. A straightforward way to achieve this is by sorting the `capacity` array in descending order and then picking boxes one by one until all apples are accommodated.
**Time:** O(n + m log m), where `n` is the length of `apple` and `m` is the length of `capacity`. Summing the apples takes O(n) time. Sorting the capacities takes O(m log m) time. The final loop takes at most O(m) time. The sorting step dominates the complexity. · **Space:** O(log m) or O(m), depending on the implementation of the sorting algorithm. In Java, `Arrays.sort` for primitive types uses a dual-pivot quicksort, which requires O(log m) space on average for the recursion stack.
**Pros:** Simple to understand and implement.; It's a general solution that works regardless of the range of values in the `capacity` array.
**Cons:** The O(m log m) time complexity from sorting is not the most optimal solution possible given the problem's constraints.
### Explanation
The algorithm proceeds in these steps:
1.  Calculate the total number of apples by summing all elements in the `apple` array. Let's call this `totalApples`.
2.  If `totalApples` is zero, no boxes are needed, so we return 0.
3.  Sort the `capacity` array. To easily access the largest capacities, we can sort it in ascending order and iterate from the end, or sort it in descending order and iterate from the beginning.
4.  Initialize a `boxesCount` to 0. Iterate through the sorted capacities (from largest to smallest).
5.  In each iteration, subtract the current box's capacity from `totalApples` and increment `boxesCount`.
6.  Continue this process until `totalApples` is less than or equal to zero.
7.  The final `boxesCount` is the minimum number of boxes required.

```java
import java.util.Arrays;

class Solution {
    public int minimumBoxes(int[] apple, int[] capacity) {
        int totalApples = 0;
        for (int a : apple) {
            totalApples += a;
        }

        if (totalApples == 0) {
            return 0;
        }

        // Sort capacity in ascending order
        Arrays.sort(capacity);

        int boxesCount = 0;
        // Iterate from the end to use largest capacities first
        for (int i = capacity.length - 1; i >= 0; i--) {
            totalApples -= capacity[i];
            boxesCount++;
            if (totalApples <= 0) {
                break;
            }
        }
        return boxesCount;
    }
}
```
### Algorithm
- Calculate `totalApples` by summing the `apple` array.
- If `totalApples` is 0, return 0.
- Sort the `capacity` array in ascending order.
- Initialize `boxesCount = 0`.
- Iterate through the `capacity` array from the last element to the first.
  - Subtract the current capacity from `totalApples`.
  - Increment `boxesCount`.
  - If `totalApples` is now less than or equal to 0, break the loop.
- Return `boxesCount`.

## Optimized Greedy Approach using a Frequency Array
This approach enhances the greedy strategy by avoiding a comparison-based sort. Given that the capacity values are limited to a small range (1 to 50), we can use a frequency array (a form of counting sort) to organize the boxes by capacity. This allows us to access the largest capacity boxes in constant time and leads to a more efficient linear time solution.
**Time:** O(n + m + C), where `n` is the length of `apple`, `m` is the length of `capacity`, and `C` is the maximum possible capacity (50). This simplifies to O(n + m) because C is a constant. This is a linear time complexity, which is more efficient than the sorting approach. · **Space:** O(C), where `C` is the maximum capacity. Since `C` is a constant (50), the space complexity is O(1).
**Pros:** Most efficient solution with linear time complexity.; Uses constant extra space, making it very memory-efficient.
**Cons:** This approach is specialized for problems where the range of input values (capacities) is small and bounded. It would be less practical if capacities could be very large.
### Explanation
The improved algorithm works as follows:
1.  As before, calculate the `totalApples` by summing the `apple` array.
2.  Create a frequency array, `counts`, of size 51 (to cover capacities 1-50), initialized to all zeros.
3.  Iterate through the `capacity` array. For each capacity `c`, increment `counts[c]`. This step takes O(m) time and groups all boxes by their capacity.
4.  Initialize `boxesCount = 0`.
5.  Iterate from the maximum possible capacity, 50, down to 1.
6.  For each capacity `c`, check `counts[c]` to see how many boxes of this size are available.
7.  Use these boxes one by one, decrementing `totalApples` and incrementing `boxesCount` for each box used, until `totalApples` is covered or you run out of boxes of capacity `c`.
8.  As soon as `totalApples` becomes less than or equal to 0, we have found our answer and can return `boxesCount` immediately.

```java
class Solution {
    public int minimumBoxes(int[] apple, int[] capacity) {
        int totalApples = 0;
        for (int a : apple) {
            totalApples += a;
        }

        if (totalApples == 0) {
            return 0;
        }

        // Frequency array for capacities 1-50
        int[] counts = new int[51];
        for (int cap : capacity) {
            counts[cap]++;
        }

        int boxesCount = 0;
        // Iterate from largest capacity down to smallest
        for (int c = 50; c >= 1; c--) {
            int numBoxesAvailable = counts[c];
            for (int i = 0; i < numBoxesAvailable; i++) {
                boxesCount++;
                totalApples -= c;
                if (totalApples <= 0) {
                    return boxesCount;
                }
            }
        }
        return boxesCount; // Should be unreachable given problem constraints
    }
}
```
### Algorithm
- Calculate `totalApples` by summing the `apple` array.
- If `totalApples` is 0, return 0.
- Create a frequency array `counts` of size 51.
- Populate `counts` by iterating through the `capacity` array: `counts[cap]++`.
- Initialize `boxesCount = 0`.
- Iterate `c` from 50 down to 1:
  - Get the number of available boxes `numBoxes = counts[c]`.
  - Loop `numBoxes` times:
    - Increment `boxesCount`.
    - Subtract `c` from `totalApples`.
    - If `totalApples <= 0`, return `boxesCount`.
- Return `boxesCount`.

# Solutions
### Java

```java
class Solution {
public
  int minimumBoxes(int[] apple, int[] capacity) {
    Arrays.sort(capacity);
    int s = 0;
    for (int x : apple) {
      s += x;
    }
    for (int i = 1, n = capacity.length;; ++i) {
      s -= capacity[n - i];
      if (s <= 0) {
        return i;
      }
    }
  }
}

```

### CPP

```cpp
class Solution {
public:
  int minimumBoxes(vector<int> &apple, vector<int> &capacity) {
    sort(capacity.rbegin(), capacity.rend());
    int s = accumulate(apple.begin(), apple.end(), 0);
    for (int i = 1;; ++i) {
      s -= capacity[i - 1];
      if (s <= 0) {
        return i;
      }
    }
  }
};

```

### Python

```python
class Solution:
    def minimumBoxes(self, apple: List[int], capacity: List[int]) -> int: capacity . sort(reverse=True) s = sum(apple) for i, c in enumerate(capacity, 1): s -= c if s <= 0: return i

```
