135. 分發糖果

小橋落花流水發表於2020-12-24

135. 分發糖果

老師想給孩子們分發糖果,有 N 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。

你需要按照以下要求,幫助老師給這些孩子分發糖果:

  • 每個孩子至少分配到 1 個糖果。
  • 相鄰的孩子中,評分高的孩子必須獲得更多的糖果。

那麼這樣下來,老師至少需要準備多少顆糖果呢?

示例 1:

輸入: [1,0,2]
輸出: 5
解釋: 你可以分別給這三個孩子分發 2、1、2 顆糖果。


示例 2:

輸入: [1,2,2]
輸出: 4
解釋: 你可以分別給這三個孩子分發 1、2、1 顆糖果。
     第三個孩子只得到 1 顆糖果,這已滿足上述兩個條件。


基本思路:本問題可以拆分成兩個部分,從左往右和從右往左看都符合要求:

  • 從左往右看,若ratings[i]>ratings[i-1],那麼第i個孩子一定比i-1個孩子獲得的果子多,否則為1,
  • 從右往左看,若ratings[i]>ratings[i+1],那麼第i個孩子一定比i+1個孩子獲得的果子多,否則為1,
  • 對於同一個位置的,去兩者之間最大的就一定可以滿足要求
    int candy(vector<int>& ratings) {
         int len=ratings.size();
        int ans=0;
        int cnt=1;
        vector<int> leftCal(len,0);
        for(int i=1;i<len;i++){
            if(ratings[i]>ratings[i-1])
                cnt++;
            else
                cnt=1;
            leftCal[i]=cnt;
        }

        cnt=1;
        for(int i=len-1;i>=0;i--){
            if(i<len-1&&ratings[i]>ratings[i+1]){
                cnt++;
            }
            else
                cnt=1;
            ans+=max(leftCal[i],cnt);
        }
        return ans;
    }

基本思路:實質上和上面的方法相同,從左往右看,如果單增和上述的方法相同;但是如果遇到單減序列,可以看作從右往左的單增序列,或者是將遞減序列逆轉,

  • 對於一個先增後減的序列,頂點屬於誰?主要看左右兩邊序列的長度
    int candy(vector<int>& ratings) {
        int inc=1,des=0,res=1,len=ratings.size();
        for(int i=1;i<len;i++){
            if(ratings[i]>=ratings[i-1]){
                dec=0;
                pre=(ratings[i]==ratings[i-1])?1:pre+1;
                res+=pre;
                inc=pre;  //記錄嚴格遞增的元素個數
            }
            else{
                dec++;
                if(inc==dec){  //說明從右往左看更大,頂點算在遞減序列上
                    dec++;
                }
                res+=dec;
                pre=1;
            }
        }

        return ans;
    }

 

相關文章