Facebook Pixel

2600. K Items With the Maximum Sum

Problem Description

You have a bag containing items with numbers written on them. Each item has exactly one of three values: 1, 0, or -1.

The bag starts with:

  • numOnes items with value 1
  • numZeros items with value 0
  • numNegOnes items with value -1

Your task is to pick exactly k items from the bag and maximize the sum of the values on those items.

For example, if you have 3 items with 1, 2 items with 0, 4 items with -1, and need to pick k = 5 items, you would pick all 3 items with 1 and 2 items with 0 to get a maximum sum of 3.

The strategy is straightforward: to maximize the sum, you should prioritize picking items with higher values. Pick items with 1 first, then items with 0, and finally items with -1 only if necessary.

The solution handles three cases:

  • If there are at least k items with value 1, pick k of them for a sum of k
  • If you need more items after taking all the 1s, take items with value 0 (which don't change the sum)
  • If you still need more items after taking all 1s and 0s, you must take some -1s, which will decrease your sum
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is that since we want to maximize the sum, we should be greedy about which items to pick. Each item contributes a fixed value to our sum: 1, 0, or -1.

Think of it like filling a basket where you want the highest total value. Naturally, you'd want to pick the most valuable items first. Items with value 1 increase our sum, items with value 0 don't change it, and items with value -1 decrease it.

Since we must pick exactly k items, the optimal strategy becomes clear:

  1. First, take as many 1s as possible (up to k items)
  2. If we still need more items, take 0s (they're neutral - won't hurt our sum)
  3. Only if we absolutely must, take -1s to reach exactly k items

This greedy approach works because there's no benefit to taking a lower-valued item when a higher-valued one is available. Taking a 0 instead of a 1 would only decrease our sum, and taking a -1 instead of a 0 or 1 would decrease it even more.

The mathematical logic follows directly: if we have enough 1s to fill our quota of k items, our sum is simply k. If not, we take all numOnes items with value 1, fill up with 0s if possible, and reluctantly take -1s for any remaining slots. The final sum becomes numOnes - (number of -1s taken), where the number of -1s taken is k - numOnes - numZeros.

Learn more about Greedy and Math patterns.

Solution Approach

The implementation follows a straightforward greedy algorithm with conditional checks to determine how many items of each type to select.

Case 1: We have enough 1s

if numOnes >= k:
    return k

If the number of items with value 1 is at least k, we simply take k of them. Each contributes 1 to the sum, so the total is k.

Case 2: We need to use some 0s

if numZeros >= k - numOnes:
    return numOnes

If we don't have enough 1s, we take all numOnes of them first. Then we check if we have enough 0s to make up the difference (k - numOnes more items needed). If yes, we take those 0s. Since 0s don't affect the sum, our total remains numOnes.

Case 3: We must take some -1s

return numOnes - (k - numOnes - numZeros)

If we still need more items after taking all 1s and all 0s, we're forced to take some -1s. The number of -1s we need is k - numOnes - numZeros. Each -1 decreases our sum by 1, so the final sum is:

  • Start with numOnes (from all the 1s)
  • Subtract (k - numOnes - numZeros) (the penalty from the -1s)

The algorithm runs in O(1) time and space since it only performs a few arithmetic operations and comparisons without any loops or additional data structures. The beauty of this solution lies in its simplicity - by thinking greedily, we avoid complex calculations and arrive at an elegant solution through simple conditional logic.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through an example with numOnes = 2, numZeros = 1, numNegOnes = 4, and we need to pick k = 5 items.

Step 1: Check if we have enough 1s

  • We have 2 items with value 1, but need to pick 5 items total
  • Since numOnes (2) < k (5), we can't fill our quota with just 1s
  • Take all 2 items with value 1: sum so far = 2

Step 2: Check if we can fill the rest with 0s

  • After taking 2 ones, we still need 5 - 2 = 3 more items
  • We have 1 item with value 0, but need 3 more items
  • Since numZeros (1) < k - numOnes (3), we can't fill the remaining slots with just 0s
  • Take the 1 item with value 0: sum remains = 2

Step 3: Fill remaining slots with -1s

  • After taking all 1s and 0s, we've picked 2 + 1 = 3 items
  • We still need 5 - 3 = 2 more items
  • We must take 2 items with value -1
  • Each -1 decreases our sum: final sum = 2 - 2 = 0

Verification using the formula: Using Case 3: numOnes - (k - numOnes - numZeros) = 2 - (5 - 2 - 1) = 2 - 2 = 0

Therefore, the maximum possible sum when picking exactly 5 items is 0.

Solution Implementation

1class Solution:
2    def kItemsWithMaximumSum(
3        self, numOnes: int, numZeros: int, numNegOnes: int, k: int
4    ) -> int:
5        """
6        Calculate the maximum sum by selecting exactly k items from bags containing 1s, 0s, and -1s.
7      
8        Strategy: Greedily select items in order of value (1s first, then 0s, then -1s).
9      
10        Args:
11            numOnes: Number of items with value 1
12            numZeros: Number of items with value 0
13            numNegOnes: Number of items with value -1
14            k: Total number of items to select
15          
16        Returns:
17            Maximum possible sum of k selected items
18        """
19      
20        # Case 1: If we have enough 1s to fulfill k items, take all k from 1s
21        if numOnes >= k:
22            return k
23      
24        # Case 2: If we need more than available 1s, take all 1s first
25        # Then check if we can fill the remaining with 0s (which don't affect sum)
26        if numZeros >= k - numOnes:
27            return numOnes
28      
29        # Case 3: We need all 1s, all 0s, and some -1s
30        # Sum = all 1s + 0s (contribute 0) + required -1s
31        # Required -1s = k - numOnes - numZeros
32        return numOnes - (k - numOnes - numZeros)
33
1class Solution {
2    public int kItemsWithMaximumSum(int numOnes, int numZeros, int numNegOnes, int k) {
3        // If we have enough 1s to fulfill k items, take all 1s for maximum sum
4        if (numOnes >= k) {
5            return k;
6        }
7      
8        // If we need more than available 1s, take all 1s and fill remaining with 0s
9        // This gives us sum = numOnes (since 0s don't contribute to sum)
10        if (numZeros >= k - numOnes) {
11            return numOnes;
12        }
13      
14        // If we need all 1s, all 0s, and some -1s to reach k items
15        // Sum = all 1s minus the number of -1s we need to take
16        // Number of -1s needed = k - numOnes - numZeros
17        return numOnes - (k - numOnes - numZeros);
18    }
19}
20
1class Solution {
2public:
3    int kItemsWithMaximumSum(int numOnes, int numZeros, int numNegOnes, int k) {
4        // If we have enough ones to satisfy k items, take all k ones
5        // This gives us the maximum sum of k
6        if (numOnes >= k) {
7            return k;
8        }
9      
10        // If we've taken all ones but still need more items,
11        // check if zeros can fill the remaining slots
12        // Taking zeros doesn't change the sum, so return just the count of ones
13        if (numZeros >= k - numOnes) {
14            return numOnes;
15        }
16      
17        // We've taken all ones and all zeros, but still need more items
18        // We must take some negative ones to reach k items
19        // Sum = all ones - (number of negative ones we need to take)
20        return numOnes - (k - numOnes - numZeros);
21    }
22};
23
1/**
2 * Calculate the maximum sum of k items from a bag containing ones, zeros, and negative ones
3 * @param numOnes - Number of items with value 1
4 * @param numZeros - Number of items with value 0
5 * @param numNegOnes - Number of items with value -1
6 * @param k - Total number of items to select
7 * @returns Maximum possible sum of k items
8 */
9function kItemsWithMaximumSum(
10    numOnes: number,
11    numZeros: number,
12    numNegOnes: number,
13    k: number
14): number {
15    // If we have enough ones to satisfy k, take all k ones for maximum sum
16    if (numOnes >= k) {
17        return k;
18    }
19  
20    // If we can fill remaining slots with zeros after taking all ones
21    // The sum equals the number of ones (since zeros don't affect the sum)
22    if (numZeros >= k - numOnes) {
23        return numOnes;
24    }
25  
26    // We must take some negative ones after exhausting all ones and zeros
27    // Sum = all ones - (number of negative ones needed)
28    const negativeOnesNeeded: number = k - numOnes - numZeros;
29    return numOnes - negativeOnesNeeded;
30}
31

Time and Space Complexity

The time complexity is O(1) because the algorithm only performs a fixed number of arithmetic operations and comparisons regardless of the input values. There are no loops, recursive calls, or operations that depend on the size of the input parameters.

The space complexity is O(1) because the algorithm only uses a constant amount of extra space. No additional data structures are created, and the space usage does not scale with the input values.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Integer Overflow in Subtraction Operations

One common mistake is not considering the order of operations when calculating the number of -1s needed. Developers might write:

# Incorrect approach that could cause confusion
return numOnes - k + numOnes + numZeros

This rearrangement, while mathematically equivalent, is less intuitive and more prone to errors. The original formula numOnes - (k - numOnes - numZeros) clearly shows we're subtracting the count of -1s from the sum of 1s.

Solution: Stick to the logical grouping that matches the problem's narrative: start with numOnes and subtract the penalty from taking -1s.

Pitfall 2: Forgetting Edge Case Validation

Developers might assume the input always allows for selecting exactly k items without verifying:

# Missing validation
def kItemsWithMaximumSum(self, numOnes, numZeros, numNegOnes, k):
    # What if k > numOnes + numZeros + numNegOnes?
    if numOnes >= k:
        return k
    # ... rest of the code

Solution: Add a validation check or document the assumption:

def kItemsWithMaximumSum(self, numOnes, numZeros, numNegOnes, k):
    # Ensure we have enough items (optional based on problem constraints)
    total_items = numOnes + numZeros + numNegOnes
    if k > total_items:
        raise ValueError(f"Cannot select {k} items from {total_items} available items")
  
    # Continue with original logic
    if numOnes >= k:
        return k
    # ...

Pitfall 3: Overcomplicating with Loops or Arrays

Some developers might instinctively create arrays or use loops:

# Unnecessarily complex approach
def kItemsWithMaximumSum(self, numOnes, numZeros, numNegOnes, k):
    items = [1] * numOnes + [0] * numZeros + [-1] * numNegOnes
    items.sort(reverse=True)
    return sum(items[:k])

This approach works but has O(n) space complexity and O(n log n) time complexity where n = numOnes + numZeros + numNegOnes.

Solution: Recognize that since we know the exact values and their counts, we can solve this mathematically in O(1) time and space without creating any data structures.

Pitfall 4: Incorrect Conditional Logic Order

Mixing up the conditions or using elif incorrectly:

# Incorrect - this would return wrong results
def kItemsWithMaximumSum(self, numOnes, numZeros, numNegOnes, k):
    if numOnes >= k:
        return k
    elif numOnes + numZeros >= k:  # Wrong condition
        return numOnes
    else:
        return numOnes - (k - numOnes - numZeros)

The second condition should check if numZeros >= k - numOnes, not if numOnes + numZeros >= k.

Solution: Carefully think through each condition:

  1. Do we have enough 1s alone?
  2. After taking all 1s, do we have enough 0s for the remainder?
  3. If not, we must take some -1s.
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which of these properties could exist for a graph but not a tree?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More