贪心算法:将数组和减半的最少操作次数

题目描述:

给你一个正整数数组 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 = 15.5 。
我们需要 3 个操作实现题目要求,所以返回 3 。
可以证明,无法通过少于 3 个操作使数组和减少至少一半。

提示:

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

题目解析:

解析很简单,但实操很难!!!给定一个正整数数组,从任意选出数组中的几个元素,通过一系列操作,让它恰好减小到一般,在此基础上,对这个已经减半的数组继续进行减半。最后,返回数组和和减半的最少操作次数。

示例的话同学们自己去看解释!!!

嗯,想了想还是讲讲吧!!!

看!!!nums[5,19,8,1],sum=33,和的一半:16.5,从数组nums中任意选择元素19减半,9.5,sum任然>=16.5,继续上述操作,任意选择元素9.5减半,4.75,发现还是不行,任意选择元素8减半,4,这时满足条件,即最小操作次数为3。

算法原理:贪心算法

贪心策略:

贪心策略每一道题有每一道题的贪心策略难点))优先选择当前数组中最大的元素进行减半,直至整个数组和小于数组和的一半。

那么,如何实现在代码上呢?(优先考虑数据结构

数据结构:<堆>

帮助大家复习下基础知识:优先队列头文件:#include

堆:堆- CSDN搜索   /   【数据结构】堆(Heap)详解_堆heap-CSDN博客

优先队列:priority_queue(优先队列)讲解_priority——queue-CSDN博客

代码编写:

class SOlution {
public:
	int hiuwh(vector& nums) {
		priority_queue heap;  //优先队列
		double sum = 0.0;  //数组和
		for (int x : nums) {  //遍历所有的数组元素
			heap.push(x);  //入队
			sum += x;
		}
		sum /= 2.0;
		int count = 0;  //计数器
		while (sum > 0) {
			double t = heap.top()/2.0;  //贪心策略:优先选择最大元素
			heap.pop();  //每循环依次,pop掉一次
			sum -= t; //数组减半:sum /= 2.0;
			count++;  //每减半一次,计数一次
			heap.push(t);  //重新入队
		}
		return count;  //当sum<=0时,直接返回count;
	}
};

 最后关于贪心策略的证明我这里就不证明了,有的贪心策略证明很麻烦很浪费时间,数学底子好的可以试试。

你可能感兴趣的:(贪心算法精讲,贪心算法,算法,数据结构,c语言,c++,动态规划)