{x}
blog image

Largest Values From Labels

You are given n item's value and label as two integer arrays values and labels. You are also given two integers numWanted and useLimit.

Your task is to find a subset of items with the maximum sum of their values such that:

  • The number of items is at most numWanted.
  • The number of items with the same label is at most useLimit.

Return the maximum sum.

 

Example 1:

Input: values = [5,4,3,2,1], labels = [1,1,2,2,3], numWanted = 3, useLimit = 1

Output: 9

Explanation:

The subset chosen is the first, third, and fifth items with the sum of values 5 + 3 + 1.

Example 2:

Input: values = [5,4,3,2,1], labels = [1,3,3,3,2], numWanted = 3, useLimit = 2

Output: 12

Explanation:

The subset chosen is the first, second, and third items with the sum of values 5 + 4 + 3.

Example 3:

Input: values = [9,8,8,7,6], labels = [0,0,0,1,1], numWanted = 3, useLimit = 1

Output: 16

Explanation:

The subset chosen is the first and fourth items with the sum of values 9 + 7.

 

Constraints:

  • n == values.length == labels.length
  • 1 <= n <= 2 * 104
  • 0 <= values[i], labels[i] <= 2 * 104
  • 1 <= numWanted, useLimit <= n

Solution Explanation

This problem requires finding a subset of items with the maximum sum of values, subject to two constraints: the number of items is at most numWanted, and the number of items with the same label is at most useLimit. The optimal approach is a greedy algorithm combined with sorting and efficient data structures.

Approach:

  1. Pairing Values and Labels: We first create pairs of (value, label) from the input arrays values and labels. This allows us to easily track both pieces of information together.

  2. Sorting by Value: We sort these pairs in descending order based on their values. This ensures that we consider the highest-value items first, maximizing the sum.

  3. Counting Labels: We use a dictionary or hash map (cnt in the code) to keep track of how many items with each label have already been included in our subset.

  4. Greedy Selection: We iterate through the sorted pairs. For each pair:

    • If the count of its label (cnt[label]) is less than useLimit, we can include this item.
    • We increment the label count (cnt[label] += 1) and add the item's value to the total sum (ans += value).
    • We also increment a counter (num) to keep track of the total number of items selected.
    • The loop continues until either we've selected numWanted items or we've iterated through all pairs.
  5. Return the Maximum Sum: Finally, we return the accumulated sum ans.

Time Complexity Analysis:

  • Sorting the pairs takes O(N log N) time, where N is the number of items.
  • Iterating through the sorted pairs and updating the count takes O(N) time in the best and average cases (using a hash map for efficient lookups). In the worst case (e.g., all labels are the same), it might take O(N*log N) if you use tree-based maps. However, with hash maps, O(N) is typical.
  • Therefore, the overall time complexity is dominated by the sorting step: O(N log N).

Space Complexity Analysis:

  • The space used by the pairs array is O(N).
  • The space used by the cnt dictionary (or hash map) is at most O(M), where M is the number of unique labels. In the worst case, M could be N, but often it's much smaller.
  • Hence, the overall space complexity is O(N).

Code Examples (with detailed comments):

The provided code examples in Python, Java, C++, Go, and TypeScript all implement this algorithm. The core logic remains consistent across languages, with only syntax and data structure implementations varying slightly. For example, Python uses Counter for efficient label counting, while Java and C++ use HashMap and unordered_map, respectively. The Go code uses Go's built-in maps. TypeScript uses a Map. The choice of data structure affects the specific performance in different contexts (some have better worst-case performance than others).

The comments in the provided code further clarify the steps of the algorithm. The choice of using a negative value in the C++ example to simplify the sorting in a slightly less readable fashion is a matter of stylistic choice. The alternative is to use a custom comparator, which would make the code clearer at a small performance cost.