このアルゴリズムの分析をより面白くするために、次の入力を行います。
9
2
3
4
4
4
2
1
3
4
まず、子供がキャンディーを手に入れている子供の隣に座っていてx、その子供が低い評価を持っている場合、最初の子供は少なくともx+1キャンディーを手に入れる必要があることに注意してください。違いを1以上にすると、キャンディーが無駄になります。差は1より大きい必要がある場合もありますが、後でそれが発生したときに説明します。
さて、キャンディーを1つだけ手に入れるべき子供たちを見つけましょう。私は、評価を山脈として視覚化し(評価が大きいほど、その時点で山が高くなります)、1つのキャンディーを取得する必要がある子供を見つけることは、山の谷(両方の隣人がより高い評価または同じ評価を持つポイント)を見つけることとして視覚化します。範囲。与えられた例は次のようになります(谷は矢印で示されています):
  ***   *
 ****  **
****** **
*********
^  ^  ^
このプロセスの目的のために、この線の開始前と終了後に「無限」の高さの2つのピークがあると仮定します。(私が無限と言うときは、入力で可能な値よりも大きいことを意味するので10^5+1、「無限」に使用できます。実際には、問題設定者が入力データにバグを持っている場合に備えて、それよりも大きい値を使用します。)
次のコードを使用して、谷を簡単に見つけることができます。
ratings = ...
N = ...
valleys = []
def get_rating(i):
    if i < 0 or i > N-1:
        return INFINITY
    return ratings[i]
for i from 0 to N-1:
    if get_rating(i) <= get_rating(i-1) and get_rating(i) <= get_rating(i+1):
        valleys.append(i)
配列valleysには谷のインデックスが含まれています。私たちは、谷を代表する各子供が1つのキャンディーを手に入れるべきであることを知っています。説明のために、谷がインデックス4にあると仮定します。これで、インデックス3と5の子供は少なくとも2つのキャンディーを入手する必要があることがわかりました。インデックス2の子供がインデックス3の子供よりも高い評価を持っている場合、その子供は少なくとも3つのキャンディーを手に入れる必要があります。2以下の場合も同様です。同様に6以上の場合。
私が「少なくとも」と言っていることに注意してください。これはピークが原因です(評価が隣人の両方よりも高い子供、谷とは異なり、この定義に平等を含めないことに注意してください)。ピークには2つの最小制約があり、2つのうち大きい方を選択するだけです。
これで、次のコードを使用して、各子供が手に入れるべきキャンディーの数を見つけることができます。
candies = [0] * N # An array of N 0s
for valley_idx in valleys:
    candies[valley_idx] = 1
    cur_idx = valley_idx-1
    cur_candies = 2
    while cur_idx >= 0 and ratings[cur_idx] > ratings[cur_idx+1]:
        candies[cur_idx] = max(candies[cur_idx], cur_candies)
        cur_idx -= 1
        cur_candies += 1
    cur_idx = valley_idx+1
    cur_candies = 2
    while cur_idx < N and ratings[cur_idx] > ratings[cur_idx-1]:
        candies[cur_idx] = max(candies[cur_idx], cur_candies)
        cur_idx += 1
        cur_candies += 1
candies次に、教師が購入する必要のあるキャンディーの数は、配列内の値の合計です。
これを行うと、答えは18サンプル入力またはグラフの形式であることがわかります。
  * *   *
 ** ** **
*********
わずかに変更された問題ステートメントの解決策
上記の解決策では、同じ評価の隣接する子供は、他の子供との関係で取得するキャンディーの量に制限を設けないと仮定しました。代わりに、両方の子供が同じ量のキャンディーを入手する必要がある場合は、これを考慮してアルゴリズムを非常に簡単に変更できます。
基本的な考え方は、ある種のランレングスエンコーディングを行うことです。これは、同じ評価の子供が1人以上連続しているかどうかに関係なく、隣人が取得するキャンディーの量が変わらないことに気付くためです。5人の子供が5人のキャンディーを手に入れるということは、5人だけでなく、25人のキャンディーを配らなければならないことを意味するので、私たちは連続した子供の数を追跡する必要がありますmultipliers。次のコードを使用して、新しいratings配列と配列を見つけますmultipliers。
new_ratings = [ratings[0]]
multipliers = [1]
for i from 1 to N-1:
    if ratings[i] == new_ratings[len(new_ratings)-1]:
        multipliers[len(new_ratings)-1] += 1
    else:
        new_ratings.append(ratings[i])
        multipliers.append(1)
ここで、配列に対して元のアルゴリズムを実行し、new_ratings配列を取得しcandiesます。次に、実際に実行できるキャンディーの量を取得します。
answer = 0
for i from 0 to len(new_ratings)-1:
    answer += multipliers[i] * candies[i]
これを行うと、答えは20サンプル入力またはグラフの形式であることがわかります。
  ***   *
 ***** **
*********