leetcode
leetcode 1951 ~ 2000
K 次增加后的最大乘积

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)

代码细节讲解

🦆
为什么在算法中需要添加一个非常大的数作为哨兵至数组末尾?这种做法有什么具体的作用?
在算法中添加一个非常大的数作为哨兵到数组末尾主要是为了处理边界情况。这样做可以避免在增加操作时需要频繁检查是否已经到达数组的末尾。具体来说,这个哨兵元素保证在进行元素值提升的时候,总有一个“下一个不同的值”可以参考,即使实际上已经处理到了原始数组的最后。这样可以简化逻辑并保持循环中的条件判断一致,使代码更加简洁和易于理解。
🦆
在进行每一段的增加操作时,如何决定是将整段提升至下一个值,还是均匀分配增加次数,或者只对部分元素进行增加?
决定增加操作的策略基于可用的增加次数k与当前段的长度l的比较。如果k足够将当前最小段的所有元素提升至下一个不同的值(即l * dif <= k,其中dif是当前值与下一个不同值的差),则选择将整段提升。如果k不足以完成这一提升但足以均匀分配(即l <= k),则选择均匀分配增加次数。如果k小于段长度l,则选择对前k个元素各增加1,以尽可能平均地利用剩余的次数。这种策略旨在最大化每次增加的效益,以尽可能均匀地提升数组的值,从而最大化最终的乘积。
🦆
在增加操作中,如果当前段的长度l大于剩余的增加次数k,为什么选择对前k个元素各增加1,而不是选择其他的增加策略?
如果当前段的长度l大于剩余的增加次数k,选择对前k个元素各增加1是为了尽可能地均匀分配有限的增加次数,从而尽可能地使增加后数组的数字均匀。这种方法帮助避免某些数字过高而其他数字仍然较低,从而最大化整个数组的乘积。这种策略是基于贪心算法的思想—即尽可能平均利用每一次增加机会,以达到最佳的整体效果。
🦆
最终计算乘积时,为什么要在每次乘法操作后立即对结果取模,这样做有什么好处?
在每次乘法操作后立即对结果取模主要是为了防止整数溢出,并保持计算结果的稳定性。因为在多次连续的乘法操作中,尤其是在元素值可能很大或数组很长的情况下,乘积很快会超过常规整数类型的存储范围。取模操作(模一个大质数,如10^9+7)可以有效控制结果在一个安全的数值范围内,同时也是许多编程比赛和实际应用中常用的方法,以确保结果的正确性和程序的健壮性。

相关问题