leetcode
leetcode 2751 ~ 2800
幸福值最大化的选择方案

幸福值最大化的选择方案

难度:

标签:

题目描述

You are given an array happiness of length n, and a positive integer k.

There are n children standing in a queue, where the ith child has happiness value happiness[i]. You want to select k children from these n children in k turns.

In each turn, when you select a child, the happiness value of all the children that have not been selected till now decreases by 1. Note that the happiness value cannot become negative and gets decremented only if it is positive.

Return the maximum sum of the happiness values of the selected children you can achieve by selecting k children.

 

Example 1:

Input: happiness = [1,2,3], k = 2
Output: 4
Explanation: We can pick 2 children in the following way:
- Pick the child with the happiness value == 3. The happiness value of the remaining children becomes [0,1].
- Pick the child with the happiness value == 1. The happiness value of the remaining child becomes [0]. Note that the happiness value cannot become less than 0.
The sum of the happiness values of the selected children is 3 + 1 = 4.

Example 2:

Input: happiness = [1,1,1,1], k = 2
Output: 1
Explanation: We can pick 2 children in the following way:
- Pick any child with the happiness value == 1. The happiness value of the remaining children becomes [0,0,0].
- Pick the child with the happiness value == 0. The happiness value of the remaining child becomes [0,0].
The sum of the happiness values of the selected children is 1 + 0 = 1.

Example 3:

Input: happiness = [2,3,4,5], k = 1
Output: 5
Explanation: We can pick 1 child in the following way:
- Pick the child with the happiness value == 5. The happiness value of the remaining children becomes [1,2,3].
The sum of the happiness values of the selected children is 5.

 

Constraints:

  • 1 <= n == happiness.length <= 2 * 105
  • 1 <= happiness[i] <= 108
  • 1 <= k <= n

代码结果

运行时间: 144 ms, 内存: 39.7 MB


/* 思路:
 1. 使用Java Stream对幸福值数组进行排序。
 2. 使用stream的限制功能选取前k个最大的幸福值。
 3. 将选中的幸福值求和作为结果。
*/

import java.util.Arrays;

public class Solution {
    public int maxHappiness(int[] happiness, int k) {
        // 使用Stream排序并选取前k个最大的幸福值
        return Arrays.stream(happiness)
                     .sorted()
                     .skip(happiness.length - k)
                     .sum();
    }
}

解释

方法:

首先,题解中对happiness数组进行了降序排序,这样可以直接从最大的幸福值开始选择。接下来,会检查第k个元素是否大于等于k,如果是,直接计算前k个元素的和减去一个特定的序列和(0到k-1的和),这是因为每次选择都会使得未选择的元素幸福值减1。如果第k个元素小于k,那么需要寻找一个最大的t(t<=k),使得每个happiness[i]都至少为t,此时计算前t个元素的和减去序列和。这种方法确保了在每轮减少幸福值的情况下,能够获得最大的幸福值总和。

时间复杂度:

O(n log n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在决定选择孩子的数量t时,题解中将t初始化为0然后逐个检查happiness[i]是否大于等于t?这种方法如何确保达到最优解?
在题解中,t代表可以连续选择的孩子的数量。初始化t为0是因为开始时没有孩子被选择。通过逐个检查每个孩子的幸福值是否大于等于t,可以确保每次选择后,剩余的每个孩子的幸福值至少减少1,而且保证选择的孩子数量不超过他们原始的幸福值。这种方法保证了在每一轮选择中,我们都取得了当前可能的最大幸福值,因为每增加一个孩子,我们都确保了这个孩子的幸福值在减少后仍然是正数,从而最大化了总幸福值。
🦆
题解中提到如果happiness[k-1] >= k则可以直接计算前k个元素的和减去序列和,这种情况下为什么不需要再考虑后续的幸福值可能减少的问题?
如果happiness[k-1](即第k个最大的幸福值)大于等于k,这意味着前k个孩子的幸福值都至少为k。因此,即使每选择一次,所有孩子的幸福值减少1,这些孩子的幸福值在k轮选择后仍然为非负。这样,选择前k个孩子提供的总幸福值最大,且每个孩子至少可以被选择一次,不会因为幸福值的减少而影响到总选择次数。因此,在这种情况下我们可以安全地直接计算这k个孩子的幸福值和减去序列和,而不必担心后续幸福值的减少问题。
🦆
在什么情况下会触发'happiness[k-1] < k'的条件,此时如何确定最大的t值以确保选取的孩子数量是最优的?
当happiness[k-1](即第k个最大的幸福值)小于k时,提示我们不能简单地选择前k个孩子,因为至少有一个孩子的幸福值少于k,意味着在连续选择k次后,这个孩子的幸福值会变为负数,违反了选择规则。此时,我们需要重新确定最大的t值,即最大的连续可选择孩子数,使得每个孩子的幸福值在选择过程中始终不少于选择次数。通过从头开始检查每个孩子的幸福值是否至少为当前的选择次数(t),并逐步增加t,直到找到使得happiness[t-1] < t的点为止。这样,我们可以确保在选择t个孩子的过程中,每个孩子的幸福值始终满足选择条件,从而获得最大的总幸福值。

相关问题