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 value1
numZeros
items with value0
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 value1
, pickk
of them for a sum ofk
- If you need more items after taking all the
1
s, take items with value0
(which don't change the sum) - If you still need more items after taking all
1
s and0
s, you must take some-1
s, which will decrease your sum
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:
- First, take as many
1
s as possible (up tok
items) - If we still need more items, take
0
s (they're neutral - won't hurt our sum) - Only if we absolutely must, take
-1
s to reach exactlyk
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 1
s 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 0
s if possible, and reluctantly take -1
s for any remaining slots. The final sum becomes numOnes - (number of -1s taken)
, where the number of -1
s taken is k - numOnes - numZeros
.
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 1
s
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 0
s
if numZeros >= k - numOnes: return numOnes
If we don't have enough 1
s, we take all numOnes
of them first. Then we check if we have enough 0
s to make up the difference (k - numOnes
more items needed). If yes, we take those 0
s. Since 0
s don't affect the sum, our total remains numOnes
.
Case 3: We must take some -1
s
return numOnes - (k - numOnes - numZeros)
If we still need more items after taking all 1
s and all 0
s, we're forced to take some -1
s. The number of -1
s we need is k - numOnes - numZeros
. Each -1
decreases our sum by 1
, so the final sum is:
- Start with
numOnes
(from all the1
s) - Subtract
(k - numOnes - numZeros)
(the penalty from the-1
s)
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 EvaluatorExample 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 -1
s 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 -1
s from the sum of 1
s.
Solution: Stick to the logical grouping that matches the problem's narrative: start with numOnes
and subtract the penalty from taking -1
s.
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:
- Do we have enough
1
s alone? - After taking all
1
s, do we have enough0
s for the remainder? - If not, we must take some
-1
s.
Which of these properties could exist for a graph but not a tree?
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!