2023-07-25每日一题
一、题目编号
2208. 将数组和减半的最少操作次数
二、题目链接
点击跳转到题目位置
三、题目描述
给你一个正整数数组 nums 。每一次操作中,你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。(注意,在后续操作中你可以对减半过的数继续执行操作)
请你返回将 nums 数组和 至少 减少一半的 最少 操作数。
示例1:
示例2:
提示:
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 107
四、解题代码
class Solution {
priority_queue<float, vector<float>, less<float>> q;
public:
int halveArray(vector<int>& nums) {
int n = nums.size();
double sum = 0;
for(int i = 0; i < n; ++i){
q.push(nums[i]);
sum += nums[i];
}
double target = (double)sum / 2;
int res = 0;
while(sum > target){
float max_num = q.top();
float num = max_num / 2;
sum -= num;
q.pop();
q.push(num);
++res;
}
return res;
}
};
五、解题思路
(1) 使用优先队列来解决该问题。首先我们求出数组中所有数字之和,因为数字最大是107 * 105,所以用double类型。后面除了数字小点的用float类型就够了,其余都使用double类型。
(2) 我们的目标是将和至少减少到最开始的一半,而且我们可以将存在的任何一个数字减少到一半,那我们要减少的更多,那么就每次减少最大的数字即可,这是贪心的思想。
(3) 我们如何得到最大的数字呢,自然考虑到优先队列,建立大根堆,这样队首的元素就是最大值。
(4)直到元素之和小于等于原来值的一半退出循环,将记录的次数输出即可。