leetcode
leetcode 2301 ~ 2350
K 件物品的最大和

K 件物品的最大和

难度:

标签:

题目描述

There is a bag that consists of items, each item has a number 1, 0, or -1 written on it.

You are given four non-negative integers numOnes, numZeros, numNegOnes, and k.

The bag initially contains:

  • numOnes items with 1s written on them.
  • numZeroes items with 0s written on them.
  • numNegOnes items with -1s written on them.

We want to pick exactly k items among the available items. Return the maximum possible sum of numbers written on the items.

 

Example 1:

Input: numOnes = 3, numZeros = 2, numNegOnes = 0, k = 2
Output: 2
Explanation: We have a bag of items with numbers written on them {1, 1, 1, 0, 0}. We take 2 items with 1 written on them and get a sum in a total of 2.
It can be proven that 2 is the maximum possible sum.

Example 2:

Input: numOnes = 3, numZeros = 2, numNegOnes = 0, k = 4
Output: 3
Explanation: We have a bag of items with numbers written on them {1, 1, 1, 0, 0}. We take 3 items with 1 written on them, and 1 item with 0 written on it, and get a sum in a total of 3.
It can be proven that 3 is the maximum possible sum.

 

Constraints:

  • 0 <= numOnes, numZeros, numNegOnes <= 50
  • 0 <= k <= numOnes + numZeros + numNegOnes

代码结果

运行时间: 19 ms, 内存: 16.0 MB


/*
 * 题目思路:
 * 要从袋子中选出恰好k件物品,使其标记数字之和最大。
 * 我们优先选择标记为1的物品,如果剩余的k还不够,则选择标记为0的物品,
 * 最后如果k还需要选择物品,则选择标记为-1的物品。
 */
import java.util.stream.IntStream;

public class MaxSumFromBagStream {
    public int getMaxSum(int numOnes, int numZeros, int numNegOnes, int k) {
        int[] items = new int[numOnes + numZeros + numNegOnes];
        IntStream.range(0, numOnes).forEach(i -> items[i] = 1);
        IntStream.range(numOnes, numOnes + numZeros).forEach(i -> items[i] = 0);
        IntStream.range(numOnes + numZeros, items.length).forEach(i -> items[i] = -1);
        return IntStream.of(items).boxed()
                .sorted((a, b) -> Integer.compare(b, a))
                .limit(k)
                .mapToInt(Integer::intValue)
                .sum();
    }

    public static void main(String[] args) {
        MaxSumFromBagStream solution = new MaxSumFromBagStream();
        System.out.println(solution.getMaxSum(3, 2, 0, 2)); // 输出: 2
        System.out.println(solution.getMaxSum(3, 2, 0, 4)); // 输出: 3
    }
}

解释

方法:

题解的核心思路是优先选取对总和贡献最大的物品。首先尽可能多地选择标记为 1 的物品,因为每个这样的物品都能为总和增加 1。当标记为 1 的物品不足以填满 k 时,选择标记为 0 的物品,这些物品不会增加也不会减少总和。如果还需要选择更多物品,最后选择标记为 -1 的物品,尽管这会减少总和。这个策略确保了在给定的物品和限制下,总和达到可能的最大值。

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中,为什么选择标记为0的物品时,没有对总和`total_sum`进行更新?
在题解中,选择标记为0的物品时没有对总和`total_sum`进行更新的原因是,这些物品的标记值为0,即它们对总和的贡献为零。因此,无论选择多少个标记为0的物品,总和都不会改变。这样的处理简化了计算,并确保了算法的效率。
🦆
如果`k`大于所有物品的总和(`numOnes + numZeros + numNegOnes`),题解中的算法如何处理这种情况?
题解中的算法逻辑已经涵盖了这种情况。当`k`大于所有物品的总和时,算法会尽可能多地选择标记为1的物品,然后是标记为0的物品,最后选择标记为-1的物品。如果`k`仍然大于所有可用物品的数量,即使选择完所有物品,`k`还有剩余,算法就会停止选择,因为没有更多的物品可选择。在这种情况下,总和将是通过选择所有标记为1和0的物品以及必要数量的标记为-1的物品得到的最大可能总和。
🦆
题解提到尽可能少地选择标记为-1的物品,但如果需要选择的数量`k`非常大,选择-1的物品是否会影响到总和达到最大值的目标?
是的,选择标记为-1的物品会影响到总和达到最大值的目标。在题解中,尽管尽量避免选择标记为-1的物品,但如果`k`非常大,以至于必须选择这些物品来满足`k`的数量要求,这将不可避免地减少总和。因此,在这种情况下,即使策略是为了最大化总和,总和仍可能受到负面影响,因为每选择一个标记为-1的物品,总和就会减少1。
🦆
题解中的算法逻辑是否考虑了所有边界情况,例如当`numOnes`, `numZeros`, 或`numNegOnes`为0时的情况?
题解中的算法逻辑确实考虑了这些边界情况。算法的设计允许在`numOnes`, `numZeros`, 或`numNegOnes`任何一个或多个为0时仍然正常工作。算法首先尝试选择尽可能多的标记为1的物品,如果不存在(即`numOnes`为0),则移至下一个标记为0的物品。此逻辑同样适用于`numZeros`和`numNegOnes`。因此,无论输入如何,算法都能正确处理不同的边界情况,并尽可能地提供最优的总和结果。

相关问题