一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
每日刷题 2021.04.10
- leetcode原题链接:leetcode-cn.com/problems/ma…
- 难度:中等
- 方法:优先队列
题目
- 给你一个非负整数数组 nums 和一个整数 k 。每次操作,你可以选择 nums 中 任一 元素并将它 增加 1 。
- 请你返回 至多 k 次操作后,能得到的 nums的 最大乘积 。由于答案可能很大,请你将答案对 10^9 + 7 取余后返回。
示例
- 示例1
输入:nums = [0,4], k = 5
输出:20
解释:将第一个数增加 5 次。
得到 nums = [5, 4] ,乘积为 5 * 4 = 20 。
可以证明 20 是能得到的最大乘积,所以我们返回 20 。
存在其他增加 nums 的方法,也能得到最大乘积。
- 示例2
输入:nums = [6,3,3,2], k = 2
输出:216
解释:将第二个数增加 1 次,将第四个数增加 1 次。
得到 nums = [6, 4, 3, 3] ,乘积为 6 * 4 * 3 * 3 = 216 。
可以证明 216 是能得到的最大乘积,所以我们返回 216 。
存在其他增加 nums 的方法,也能得到最大乘积。
提示
1 <= nums.length, k <= 10^50 <= nums[i] <= 10^6
解题思路
- 在
js的语法内,貌似没有优先队列这样的现成的数据结构,但是后面搜查到leetcode库中存在优先队列的数据结构。- 最小优先队列
MinPriorityQueue - 最大优先队列
MaxPriorityQueue
- 最小优先队列
- 根据数学知识可知,想要获得乘积的最大值,那么需要尽可能的将所有的边变得相等,差值最小。
- 因此,想到了使用最小优先队列的做法,通过将
nums中的所有数值,存入到优先队列中queue.enqueue(num)。后续每次只需要从最小优先队列中获取队列头部的元素queue.dequeue(),就是当前的所有数中的最小值,每次将获取到的数值+1后,再塞回到最小优先队列中,在k次操作后,一定是最大乘积。
注意
- 取模的注意事项:
res = res * element % mod;,最开始写成res *= element % mod;出错了,因为其会先运算模运算%,在运算*=,这样的话,模运算就没有起到效果,数据还是会因为很大而溢出。 - 位运算:按位与的注意事项,按位与符号的优先级比较低,因此在写表达式的时候,最好按照顺序标记好,不然就会出错。
AC代码
var maximumProduct = function(nums, k) {
let mod = 1000000000 + 7;
let len = nums.length;
const queue = new MinPriorityQueue();
for (const num of nums) {
queue.enqueue(num)
}
// console.log(queue)
while(k != 0) {
let {element} = queue.dequeue()
element++;
// console.log(element)
queue.enqueue(element);
k--;
}
let res = 1;
while(queue.size() != 0) {
let {element} = queue.dequeue()
res = res * element % mod;
}
return res;
};
总结
- 注意,
1000000000 + 7在js的代码中,可以直接书写1e9 + 7, 避免在书写0的时候出错,节省时间,更高效。