Labeled Items Maximum Sum
You are given a list of values and a list of labels. The ith element in labels represents the label of the ith element. Similarly, the ith element in values represents the value associated with the ith element (i.e. together, an "item" could be thought of as a label and a price).
Given a list of values, a list of labels, a limit, and wanted, return the sum of the most expensive items you can group such that the total number of items used is less than wanted and the number of any given label that is used is less than limit.
Example(s)
Example 1:
Input:
values = [5,4,3,2,1]
labels = [1,1,2,2,3]
wanted = 3
limit = 1
Output: 9
Explanation:
We can select items at indices 0, 2, and 4:
- Index 0: value 5, label 1
- Index 2: value 3, label 2
- Index 4: value 1, label 3
Sum = 5 + 3 + 1 = 9
Each label is used at most once (limit = 1), and we use 3 items (wanted = 3)
Example 2:
Input:
values = [10,8,6,4,2]
labels = [1,1,1,2,2]
wanted = 3
limit = 2
Output: 18
Explanation:
We can select items at indices 0, 1, and 3:
- Index 0: value 10, label 1
- Index 1: value 8, label 1 (label 1 used twice, within limit)
- Index 3: value 4, label 2
Sum = 10 + 8 + 4 = 18
Solution
The solution uses a greedy approach:
- Create pairs of (value, label, index) and sort by value in descending order
- Greedily select items while respecting constraints:
- Track how many times each label has been used
- Only select items if the label hasn't exceeded the limit
- Stop when we've selected
wanteditems
- JavaScript Solution
- Python Solution
JavaScript Solution
/**
* Find the maximum sum of items respecting label and count constraints
* @param {number[]} values - Array of item values
* @param {number[]} labels - Array of item labels
* @param {number} wanted - Maximum number of items to select
* @param {number} limit - Maximum number of items per label
* @return {number} - Maximum sum of selected items
*/
function maxSumLabeledItems(values, labels, wanted, limit) {
// Create array of items with their values, labels, and indices
const items = values.map((value, index) => ({
value,
label: labels[index],
index
}));
// Sort by value in descending order (greedy: take most expensive first)
items.sort((a, b) => b.value - a.value);
// Track how many times each label has been used
const labelCount = new Map();
let sum = 0;
let selected = 0;
// Greedily select items
for (const item of items) {
// Check if we've selected enough items
if (selected >= wanted) {
break;
}
// Check if this label has reached its limit
const currentCount = labelCount.get(item.label) || 0;
if (currentCount < limit) {
// Select this item
sum += item.value;
labelCount.set(item.label, currentCount + 1);
selected++;
}
}
return sum;
}
// Test cases
console.log(maxSumLabeledItems([5,4,3,2,1], [1,1,2,2,3], 3, 1)); // 9
console.log(maxSumLabeledItems([10,8,6,4,2], [1,1,1,2,2], 3, 2)); // 18
console.log(maxSumLabeledItems([2,6,4,8], [2,2,2,2], 2, 1)); // 14 (8 + 6)
console.log(maxSumLabeledItems([1,2,3,4,5], [1,2,3,4,5], 5, 1)); // 15 (all items)Output:
Click "Run Code" to execute the code and see the results.
Python Solution
from typing import List
def max_sum_labeled_items(
values: List[int],
labels: List[int],
wanted: int,
limit: int
) -> int:
"""
Find the maximum sum of items respecting label and count constraints
Args:
values: List of item values
labels: List of item labels
wanted: Maximum number of items to select
limit: Maximum number of items per label
Returns:
int: Maximum sum of selected items
"""
# Create list of items with their values, labels, and indices
items = [(value, labels[i], i) for i, value in enumerate(values)]
# Sort by value in descending order (greedy: take most expensive first)
items.sort(key=lambda x: x[0], reverse=True)
# Track how many times each label has been used
label_count = {}
total_sum = 0
selected = 0
# Greedily select items
for value, label, index in items:
# Check if we've selected enough items
if selected >= wanted:
break
# Check if this label has reached its limit
current_count = label_count.get(label, 0)
if current_count < limit:
# Select this item
total_sum += value
label_count[label] = current_count + 1
selected += 1
return total_sum
# Test cases
print(max_sum_labeled_items([5,4,3,2,1], [1,1,2,2,3], 3, 1)) # 9
print(max_sum_labeled_items([10,8,6,4,2], [1,1,1,2,2], 3, 2)) # 18
print(max_sum_labeled_items([2,6,4,8], [2,2,2,2], 2, 1)) # 14 (8 + 6)
print(max_sum_labeled_items([1,2,3,4,5], [1,2,3,4,5], 5, 1)) # 15 (all items)Loading Python runtime...
Output:
Click "Run Code" to execute the code and see the results.
Complexity
- Time Complexity: O(n log n) - Sorting the items by value dominates the time complexity
- Space Complexity: O(n) - Space for storing items array and label count map
Approach
The solution uses a greedy algorithm:
- Pair creation: Create tuples of (value, label, index) for each item
- Sorting: Sort items by value in descending order to prioritize expensive items
- Greedy selection: Iterate through sorted items and select them if:
- We haven't selected
wanteditems yet - The label hasn't exceeded its
limit
- We haven't selected
- Tracking: Use a map/dictionary to track how many times each label has been used
Key Insights
- Greedy approach works: Since we want to maximize the sum, always selecting the most expensive available item is optimal
- Sorting is crucial: By sorting in descending order, we ensure we consider the most valuable items first
- Constraint checking: We must check both the total count (
wanted) and per-label count (limit) before selecting an item - Optimal substructure: The problem exhibits optimal substructure - selecting the best items at each step leads to the global optimum
Edge Cases
- When
wantedis 0, return 0 - When
limitis 0, return 0 (can't select any items) - When all items have the same label and
limitis less thanwanted, we can only selectlimititems - When there are fewer items than
wanted, we select all available items that respect the label constraints