题目连接c++
贪心算法
时间复杂度O(nlogN)
,N
为数组中最大的那个数。数组
1.题意就是给定一个函数,该函数有两种功能,一种就是将数组中的全部数同乘以2,另外一种就是将数组中的某个数加1。给定一个数组nums,让你将初始值全为0的数组arr经过调用给定的函数来变成nums。问最少调用次数。函数
2.刚开始模拟了一番,但由于考虑的方法不对(至于哪里不对呢,就是一开始我就把数组的值都加1了一遍,而后再同乘以2,最后再一个个补1,这么作显然不利于减小次数。至于当时为啥这么想,估计是脑子抽了),最终无果。code
3.接下来步入正题,咱们能够这么想。当初始值都为0时,咱们能够使部分值首先加1(即最终要变成的较大的值),让它们首先乘以2,不断乘,乘到必定程度再处理。但这么作有个问题,让哪部分值先变成1呢?还有就是乘到哪一种程度呢?leetcode
这个地方的确是个难点,不太容易想。若是直接模拟的话不太容易。get
数组中谁乘2的次数最多,固然是目标值最大的那个数乘的次数最多,其余目标值较小的就相对来讲乘的次数较少。咱们能够贪心地让那些乘的次数较少的包含在乘的次数最多里面,至于它具体是怎么乘的,咱们不用考虑太多,这就是贪心算法的好处。io
如何计算每一个数最终乘的次数,咱们能够分状况讨论:function
为了方便,咱们能够从目标值向初始值变化。class
对于奇数,能够先让其变为偶数(变为偶数这个过程即减1,这个须要单独记录),而后再除2,每除一次就记录一次。
对于偶数,就除2,每除一次就记录一次。可能除着除着就变成奇数了,好比250,这时候就执行上一步。
最终,数组中的值就都变成0了。
4.总之,这道题的基本思路就是求出目标数组中最大值变成0须要除2的次数,以及该数组中每一个数须要减1的次数(何时减,就是为奇数的时候减),两者相加即为答案。
class Solution { public: int minOperations(vector<int>& nums) { int len = nums.size(); int res = 0; int mx = 0; //记录乘以2的最大次数 for(int i = 0; i < len; i++){ int cnt = 0; while(nums[i]){ if(nums[i] % 2 == 1){ nums[i] -= 1; //把它变成偶数 res++; } if(nums[i] > 0){ nums[i] /= 2; ++cnt; } } mx = max(mx, cnt); } res += mx; return res; } };