1. 程式人生 > >leetcode 135. Candy 分糖果 + 很經典的貪心演算法

leetcode 135. Candy 分糖果 + 很經典的貪心演算法

There are N children standing in a line. Each child is assigned a rating value.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?

典型的貪心演算法題本身可以用貪心法來做,我們用candy[n]表示每個孩子的糖果數,遍歷過程中,如果孩子i+1的rate大於孩子i 的rate,那麼當前最好的選擇自然是:給孩子i+1的糖果數=給孩子i的糖果數+1如果孩子i+1的rate小於等於孩子i 的rate咋整?這個時候就不大好辦了,因為我們不知道當前最好的選擇是給孩子i+1多少糖果。

程式碼如下:

import java.util.Arrays;

/*
 * 典型的貪心演算法
 * 題本身可以用貪心法來做,我們用candy[n]表示每個孩子的糖果數,遍歷過程中,
 * 如果孩子i+1的rate大於孩子i 的rate,那麼當前最好的選擇自然是:給孩子i+1的糖果數=給孩子i的糖果數+1
 * 如果孩子i+1的rate小於等於孩子i 的rate咋整?這個時候就不大好辦了,
 * 因為我們不知道當前最好的選擇是給孩子i+1多少糖果。
 * 解決方法是:暫時不處理這種情況。等陣列遍歷完了,我們再一次從尾到頭遍歷陣列,
 * 這回逆過來貪心,就可以處理之前略過的孩子。
 * 最後累加candy[n]即得到最小糖果數。
 * */
public class Solution { public int candy(int[] ratings) { if(ratings==null || ratings.length<=0) return 0; int []num = new int[ratings.length]; Arrays.fill(num, 1); for(int i=1;i<ratings.length;i++) { if(ratings[i]>ratings[i-1
]) num[i]=num[i-1]+1; } for(int i=ratings.length-2;i>=0;i--) { if(ratings[i]>ratings[i+1] && num[i] < num[i+1]+1) num[i]=num[i+1]+1; } int sum=0; for(int i=0;i<num.length;i++) sum+=num[i]; return sum; } }

下面是C++的做法,這道題是的典型的貪心演算法的一個簡單應用,需要好好學習

注意反向遍歷的時候注意dp的比較

程式碼如下:

#include <iostream>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <string>
#include <climits>
#include <algorithm>
#include <sstream>
#include <functional>
#include <bitset>
#include <numeric>
#include <cmath>
#include <regex>

using namespace std;



class Solution
{
public:
    int candy(vector<int>& r)
    {
        int n = r.size();
        vector<int> dp(n, 1);
        for (int i = 1; i < n; i++)
        {
            if (r[i] > r[i - 1])
                dp[i] = dp[i - 1] + 1;
        }

        for (int i = n - 2; i >= 0; i--)
        {
            if (r[i] > r[i + 1] && dp[i] < dp[i + 1]+1)
                dp[i] = dp[i + 1] + 1;
        }

        return accumulate(dp.begin(), dp.end(), 0);
    }
};