K 次增加后的最大乘积
难度:
标签:
题目描述
代码结果
运行时间: 159 ms, 内存: 25.5 MB
/*
题目思路:
1. 给定一个数组 nums 和一个整数 k,目标是通过最多 k 次操作使得数组 nums 的乘积最大。
2. 每次操作可以将数组中的任一元素增加 1。
3. 为了使乘积最大化,应优先将数组中最小的元素进行增加。
4. 使用最小堆(优先队列)来跟踪数组中的最小元素,进行 k 次增加操作。
5. 每次从堆中取出最小元素,增加 1,再将其放回堆中。
6. 最终计算数组的乘积,并对 10^9 + 7 取余。
7. 通过 Java Stream 对数组进行操作。
*/
import java.util.Arrays;
import java.util.PriorityQueue;
public class MaxProductAfterKIncrementsStream {
public int maximumProduct(int[] nums, int k) {
int MOD = 1000000007;
PriorityQueue<Integer> minHeap = new PriorityQueue<>(Arrays.stream(nums).boxed().toList());
while (k > 0) {
int smallest = minHeap.poll();
smallest++;
minHeap.offer(smallest);
k--;
}
long product = minHeap.stream().mapToLong(i -> i).reduce(1, (a, b) -> (a * b) % MOD);
return (int) product;
}
}
解释
方法:
解题思路是首先将数组排序,然后从最小的开始增加,尽可能地让数组中的元素均匀。每次增加操作集中在数组的最小段(即从开始到某一个不再是最小值的元素),这样能最大化乘积。对于每个最小段,如果完全可以将这一段的值增加到下一个不同的值,那么进行增加操作;如果不能,则尽可能均匀地分配增加次数。继续这个操作直到用完所有k次增加机会或者处理完所有元素。最后,计算增加后的数组的乘积,并返回结果。
时间复杂度:
O(n^2)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在算法中需要添加一个非常大的数作为哨兵至数组末尾?这种做法有什么具体的作用?
▷🦆
在进行每一段的增加操作时,如何决定是将整段提升至下一个值,还是均匀分配增加次数,或者只对部分元素进行增加?
▷🦆
在增加操作中,如果当前段的长度l大于剩余的增加次数k,为什么选择对前k个元素各增加1,而不是选择其他的增加策略?
▷🦆
最终计算乘积时,为什么要在每次乘法操作后立即对结果取模,这样做有什么好处?
▷