2208. 将数组和减半的最少操作次数

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

每日刷题第71天 2021.03.21

2208. 将数组和减半的最少操作次数

题目描述

  • 给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择任意一个数并将它减小到恰好一半。(注意,在后续操作中你可以对减半过的数继续执行操作)
  • 请你返回将 nums 数组和至少减少一半的最少操作数。

示例

  • 示例1
输入:nums = [5,19,8,1]
输出:3
解释:初始 nums 的和为 5 + 19 + 8 + 1 = 33 。
以下是将数组和减少至少一半的一种方法:
选择数字 19 并减小为 9.5 。
选择数字 9.5 并减小为 4.75 。
选择数字 8 并减小为 4 。
最终数组为 [5, 4.75, 4, 1] ,和为 5 + 4.75 + 4 + 1 = 14.75 。
nums 的和减小了 33 - 14.75 = 18.25 ,减小的部分超过了初始数组和的一半,18.25 >= 33/2 = 16.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。
复制代码
  • 示例2
输入:nums = [3,8,20]
输出:3
解释:初始 nums 的和为 3 + 8 + 20 = 31 。
以下是将数组和减少至少一半的一种方法:
选择数字 20 并减小为 10 。
选择数字 10 并减小为 5 。
选择数字 3 并减小为 1.5 。
最终数组为 [1.5, 8, 5] ,和为 1.5 + 8 + 5 = 14.5 。
nums 的和减小了 31 - 14.5 = 16.5 ,减小的部分超过了初始数组和的一半, 16.5 >= 31/2 = 16.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。
复制代码

提示

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 107

思路总结

  • 本题主要考察的点:优先队列的使用PriorityQueue
  • 思路:根据题意,需要找到最少操作数,使数组和减少至一半。
  • 那么每次就需要找到当前的数组中最大的值,将其取一半,才能保证用最少的操作数使数组和减少一半

具体步骤

  • 将原数组求和,记为total,数组和的一半记为half
  • 将数组中所有的元素压入优先队列中,每次取队列中的数,一定是当前数组中最大的数。拿到当前最大的数,将其减半之后,再放入到优先队列中。
  • 以此循环,就可以保证小于half的时候,一定是最小的操作数。

AC代码

  • js是没有内置的PriorityQueue优先队列的,但是Leetcode有内置的函数MaxPriorityQueue
var halveArray = function(nums) {
    // 数组的求和函数,初始值为0 
    let total = nums.reduce((cur, next) => cur + next, 0)
    const half = total / 2
    const queue = new MaxPriorityQueue()
    for (const num of nums) {
        queue.enqueue(num, num)
    }
    let ans = 0
    while (total > half) {
        let { element } = queue.dequeue()
        ans ++
        element /= 2
        total -= element
        queue.enqueue(element, element)
    }
    return ans
};
复制代码

总结

  • 单纯考优先队列使用的题目,记住几个操作方法
    • new MaxPriorityQueue()创建队列
    • queue.enqueue()入队
    • queue.dequeue()出队

猜你喜欢

转载自juejin.im/post/7077582922609328164