LeetCode 1655 - Distribute Repeating Integers
This problem asks whether we can satisfy a set of customer requests using repeated integers from the array nums. Each customer wants a certain quantity of numbers, given by quantity[i]. The important restriction is that every number given to a single customer must be identical.
Difficulty: 🔴 Hard
Topics: Array, Hash Table, Dynamic Programming, Backtracking, Bit Manipulation, Counting, Bitmask
Solution
Problem Understanding
This problem asks whether we can satisfy a set of customer requests using repeated integers from the array nums.
Each customer wants a certain quantity of numbers, given by quantity[i]. The important restriction is that every number given to a single customer must be identical. A customer asking for 3 items cannot receive [1,2,1], they must receive something like [5,5,5].
The actual numeric values do not matter individually. What matters is how many times each value appears. For example:
-
nums = [1,1,1,2,2,3] -
Frequencies are:
-
1 -> 3 -
2 -> 2 -
3 -> 1
A customer requesting 2 items could be satisfied using value 1 or value 2, but not value 3.
The goal is to determine whether all customers can simultaneously be satisfied.
The constraints are very important:
nums.lengthcan be as large as100000- There are at most
50unique values quantity.length <= 10
The large size of nums suggests that iterating over the raw array repeatedly would be too expensive. However, the small number of customers is the key observation. Since there are at most 10 customers, we can use bitmask dynamic programming over subsets of customers.
The problem is fundamentally about assigning customer groups to frequency buckets.
Several edge cases are important:
- A customer may request more items than any frequency can provide.
- Multiple customers may need to share the same frequency bucket carefully.
- Some values in
numsmay never be used. - Customers can receive the same numeric value only if the total allocated amount does not exceed that value's frequency.
For example:
nums = [1,1,1,1]quantity = [2,2]
This works because both customers can receive value 1.
But:
nums = [1,1,1]quantity = [2,2]
This fails because the total demand exceeds the available count.
Approaches
Brute Force Approach
A brute force solution would try every possible assignment of customers to integer values.
First, we count the frequency of each distinct value in nums. Then, for every customer, we attempt to assign them to one of the available frequencies that can satisfy their demand.
The recursion would look like:
- Pick a customer
- Try every frequency bucket that still has enough remaining count
- Deduct the quantity
- Continue recursively
This approach is correct because it explores all possible valid assignments.
However, it becomes extremely slow because the number of assignments grows exponentially. Even with only 10 customers and 50 distinct frequencies, the branching factor is enormous.
The brute force solution suffers from repeated recomputation of equivalent states.
Optimal Approach, Bitmask Dynamic Programming
The key insight is that the number of customers is very small, at most 10.
This means we can represent any subset of customers using a bitmask:
0b00101means customers0and2are included- Total subsets =
2^m - Since
m <= 10, this is at most1024
Instead of assigning customers one by one naively, we precompute:
- The total quantity required for every subset of customers
Then, for each frequency bucket, we try assigning any subset of currently unserved customers that fits within that frequency.
This transforms the problem into a subset DP problem.
The DP state becomes:
- Which customer subsets have already been satisfied
This dramatically reduces repeated work.
Approach Comparison
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | Exponential, roughly O(k^m) | O(m) | Tries all assignments recursively |
| Optimal | O(n * 3^m) | O(2^m) | Uses subset DP with bitmask optimization |
Here:
k= number of unique valuesm= number of customers
Since m <= 10, 3^m is manageable.
Algorithm Walkthrough
Step 1: Count Frequencies
We first count how many times each integer appears in nums.
For example:
nums = [1,1,1,2,2,3]
frequencies = [3,2,1]
The actual integer values are irrelevant after counting.
Step 2: Precompute Subset Sums
We represent customer subsets using bitmasks.
Suppose:
quantity = [2,3,1]
Then:
| Mask | Customers | Sum |
|---|---|---|
| 001 | {0} | 2 |
| 010 | {1} | 3 |
| 011 | {0,1} | 5 |
| 111 | {0,1,2} | 6 |
We store these sums in an array:
subset_sum[mask]
This allows constant time lookup of total demand for any subset.
Step 3: Define DP State
We define:
dp[mask]
Meaning:
- Whether the subset
maskof customers can be satisfied using processed frequencies so far.
Initially:
dp[0] = True
Because satisfying zero customers is always possible.
Step 4: Process Each Frequency
For every frequency count:
count
We create a new DP array.
For every current satisfied state:
mask
We try assigning additional unsatisfied customer subsets.
Step 5: Enumerate Subsets
Suppose:
remaining = full_mask ^ mask
This represents customers not yet satisfied.
We enumerate all submasks of remaining.
For each submask:
- Compute required quantity
- Check if it fits within the current frequency
subset_sum[submask] <= count
If valid:
new_mask = mask | submask
Mark it reachable.
Step 6: Return Final Result
If:
dp[full_mask]
is true, then all customers can be satisfied.
Otherwise, return false.
Why it works
The algorithm works because every DP state represents a complete and valid assignment for a subset of customers.
When processing a frequency bucket, we consider every possible subset of remaining customers that this bucket can satisfy. Since all subsets are explored systematically, no valid arrangement is missed.
The bitmask uniquely identifies which customers have already been satisfied, preventing duplicate recomputation of equivalent states.
Because each customer subset is considered exactly through DP transitions, the algorithm guarantees correctness.
Python Solution
from typing import List
from collections import Counter
class Solution:
def canDistribute(self, nums: List[int], quantity: List[int]) -> bool:
frequencies = list(Counter(nums).values())
m = len(quantity)
full_mask = (1 << m) - 1
subset_sum = [0] * (1 << m)
for mask in range(1 << m):
total = 0
for i in range(m):
if mask & (1 << i):
total += quantity[i]
subset_sum[mask] = total
dp = [False] * (1 << m)
dp[0] = True
for count in frequencies:
next_dp = dp[:]
for mask in range(1 << m):
if not dp[mask]:
continue
remaining = full_mask ^ mask
submask = remaining
while submask:
if subset_sum[submask] <= count:
next_dp[mask | submask] = True
submask = (submask - 1) & remaining
dp = next_dp
return dp[full_mask]
The implementation begins by converting nums into frequency counts using Counter. Since customers only care about receiving equal numbers, the actual values are irrelevant.
The subset_sum array precomputes the total demand for every customer subset. This avoids recomputing sums repeatedly during DP transitions.
The DP array stores which customer subsets are currently satisfiable.
For each frequency bucket, we iterate through every reachable state and attempt to assign additional unsatisfied customer subsets.
The subset enumeration trick:
submask = (submask - 1) & remaining
efficiently iterates through all subsets of remaining.
Finally, if the full customer mask becomes reachable, all customers can be satisfied.
Go Solution
package main
func canDistribute(nums []int, quantity []int) bool {
freqMap := make(map[int]int)
for _, num := range nums {
freqMap[num]++
}
frequencies := []int{}
for _, count := range freqMap {
frequencies = append(frequencies, count)
}
m := len(quantity)
fullMask := (1 << m) - 1
subsetSum := make([]int, 1<<m)
for mask := 0; mask < (1 << m); mask++ {
total := 0
for i := 0; i < m; i++ {
if mask&(1<<i) != 0 {
total += quantity[i]
}
}
subsetSum[mask] = total
}
dp := make([]bool, 1<<m)
dp[0] = true
for _, count := range frequencies {
nextDP := make([]bool, 1<<m)
copy(nextDP, dp)
for mask := 0; mask < (1 << m); mask++ {
if !dp[mask] {
continue
}
remaining := fullMask ^ mask
submask := remaining
for submask > 0 {
if subsetSum[submask] <= count {
nextDP[mask|submask] = true
}
submask = (submask - 1) & remaining
}
}
dp = nextDP
}
return dp[fullMask]
}
The Go implementation follows the same logic as the Python version.
Instead of Counter, a standard map is used for frequency counting.
Slices are used for DP arrays and subset sums. Go does not have Python's convenient list copying syntax, so copy() is used to duplicate the DP state.
Integer overflow is not a concern because all values remain comfortably within Go's int range.
Worked Examples
Example 1
nums = [1,2,3,4]
quantity = [2]
Step 1: Frequencies
| Value | Count |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
Frequencies:
[1,1,1,1]
Step 2: Subset Sums
| Mask | Customers | Sum |
|---|---|---|
| 0 | {} | 0 |
| 1 | {0} | 2 |
Step 3: DP
Initial:
| Mask | Reachable |
|---|---|
| 0 | True |
| 1 | False |
Each frequency is 1, but customer needs 2.
No transition succeeds.
Final:
dp[1] = False
Answer:
False
Example 2
nums = [1,2,3,3]
quantity = [2]
Frequencies
[1,1,2]
Subset Sum
| Mask | Sum |
|---|---|
| 0 | 0 |
| 1 | 2 |
DP Transition
When processing frequency 2:
subset_sum[1] = 2 <= 2
So:
dp[1] = True
Answer:
True
Example 3
nums = [1,1,2,2]
quantity = [2,2]
Frequencies
[2,2]
Subset Sums
| Mask | Customers | Sum |
|---|---|---|
| 00 | {} | 0 |
| 01 | {0} | 2 |
| 10 | {1} | 2 |
| 11 | {0,1} | 4 |
First Frequency
Using first 2:
dp[01] = True
dp[10] = True
Second Frequency
From 01, assign customer 1:
dp[11] = True
Answer:
True
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(k * 3^m) | Each frequency processes all masks and their submasks |
| Space | O(2^m) | DP and subset sum arrays |
Here:
kis the number of unique integers innumsmis the number of customers
The subset enumeration technique causes the total number of (mask, submask) pairs to become 3^m, which is feasible because m <= 10.
The memory usage remains small because only arrays of size 2^m are stored.
Test Cases
from typing import List
s = Solution()
assert s.canDistribute([1,2,3,4], [2]) == False
# Single customer cannot receive two equal numbers
assert s.canDistribute([1,2,3,3], [2]) == True
# One value appears twice
assert s.canDistribute([1,1,2,2], [2,2]) == True
# Two customers matched perfectly
assert s.canDistribute([1,1,1,1], [2,2]) == True
# Same value satisfies multiple customers
assert s.canDistribute([1,1,1], [2,2]) == False
# Total demand exceeds supply
assert s.canDistribute([1,1,1,2,2,2], [3,3]) == True
# Two exact large groups
assert s.canDistribute([1,1,1,1,2], [3,2]) == False
# One customer cannot be satisfied
assert s.canDistribute([1], [1]) == True
# Smallest valid input
assert s.canDistribute([1,1,1,1,1], [1,1,1,1,1]) == True
# Many small customers using same value
assert s.canDistribute([1,2,2,3,3,3], [1,2,3]) == True
# Multiple different frequency assignments
assert s.canDistribute([1,1,2,2,3,3], [2,2,2]) == True
# Every frequency used exactly once
assert s.canDistribute([1,1,1,2,2], [4,1]) == False
# Largest customer request impossible
Test Summary
| Test | Why |
|---|---|
[1,2,3,4], [2] |
No repeated values available |
[1,2,3,3], [2] |
Single valid repeated group |
[1,1,2,2], [2,2] |
Multiple customers |
[1,1,1,1], [2,2] |
Same value split across customers |
[1,1,1], [2,2] |
Insufficient total supply |
[1,1,1,2,2,2], [3,3] |
Exact partitioning |
[1,1,1,1,2], [3,2] |
One request impossible |
[1], [1] |
Minimum size case |
[1,1,1,1,1], [1,1,1,1,1] |
Many small allocations |
[1,2,2,3,3,3], [1,2,3] |
Mixed frequency sizes |
[1,1,2,2,3,3], [2,2,2] |
All frequencies consumed |
[1,1,1,2,2], [4,1] |
Largest request exceeds frequency |
Edge Cases
One important edge case occurs when a customer requests more items than any frequency bucket contains. For example:
nums = [1,1,2,2]
quantity = [3]
No value appears three times, so the answer must be false. A naive implementation might incorrectly combine different values, but the DP solution correctly prevents this because each subset assignment is checked against a single frequency count.
Another tricky edge case is when multiple customers share the same value. For example:
nums = [1,1,1,1]
quantity = [2,2]
Both customers can receive value 1. Some incorrect solutions assume one value can satisfy only one customer. The subset-based DP naturally handles splitting a frequency bucket across multiple customers.
A third important edge case occurs when many small customer requests exist:
nums = [1,1,1,1,1]
quantity = [1,1,1,1,1]
All customers can be satisfied using the same value. This stresses whether the algorithm correctly handles many subset combinations. Since the DP explores all customer subsets systematically, it correctly identifies the valid arrangement.
A final edge case involves unused numbers:
nums = [1,1,2,3,4]
quantity = [2]
Only the two 1s matter. The remaining numbers are irrelevant. The implementation handles this naturally because frequencies that are not useful simply do not contribute successful DP transitions.