【每日一题】2208 . 将数组和减半的最少操作

【每日一题】2208 . 将数组和减半的最少操作

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

题目描述

给你一个正整数阵列 nums 。每次操作中,你 nums 可以选择任意 一个数并将其减少到大约 一半。(注意,在后续操作中你可以对减少半过的数继续执行操作)

请您返回nums 数据库并至少 减少一半的最少 操作数。

示例1:

输入: nums = [5,19,8,1]
输出: 3
解释:最终 nums 的和为 5 + 19 + 8 + 1 = 33 。
以下是减少存储量至少一半的一种方法:
选择数字 19 并减少为 9.5 。
选择 Digital 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

解题思路

思路:贪心+大根堆(优先队列)。要求将数组和至少减半的最少操作次数,那么可以每次将数组中的最大值拿出来减半,故可以维护一个大根堆,然后每次取出堆顶减半再插回去,直至至少减半。

class Solution {
public:
    int halveArray(vector<int>& nums) {
        priority_queue<double> pq(nums.begin(),nums.end());
        double sum=accumulate(nums.begin(),nums.end(),0.0);
        int count=0;
        double target=0;
        while(target<sum/2)
        {
            double top=pq.top();
            double num=top/2;
            target+=num;
            pq.pop();
            pq.push(num);
            count++;
        }
        return count;
    }
};

总结:注意一些细节。使用priority_queue<double> pq(nums.begin(),nums.end())初始化大根堆,注意是double类型的喔;使用sum=accumulate(nums.begin(),nums.end(),0.0)来累计数组和,这样可以不用for循环求和的喔;pri_que.push()向队列中添加一个元素;pri_que.pop()将队列中优先级最高的元素删除;pri_que.top()获取队列中优先级最高的元素;pri_que.size()获取队列的大小;pri_que.empty()判断队列是否为空;priority_queue<typename, container, functional> pri_que初始化优先级队列,其中typename表示数据的类型,container表示容器的类型,默认是vector容器,functional表示比较的方式,默认是大顶堆less<type>,如果是小顶堆则是greater<type>,当数据类型不是基本数据类型而是自定义数据类型时,就不能使用greater或者less比较方式了,而是需要自定义比较方式,注意,其中堆的cmp与sort的cmp相反的,即堆的>表示小根堆,堆的<表示大根堆。

猜你喜欢

转载自blog.csdn.net/qq_43779149/article/details/131911398