題目連接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; } };