leetcode1558題解【貪心】

leetcode1558.獲得目標數組的最少函數調用次數

題目連接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的次數(何時減,就是爲奇數的時候減),兩者相加即爲答案。

C++代碼

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;
    }
};

思路來源

相關文章
相關標籤/搜索