題目要求比其高的鄰居要比本身的獎勵多,那麼最少也要多一個,所有我們可以找到所有的凹點,凹點如下三種情形。
找到所有的凹點後,我們就可以從凹點處開始向左右兩個方向依次查找遞增序列,其中每個高的都要比相鄰的矮的多一個,比如1,2,5,4.我們找到凹點爲1 和4,那麼從1開始向左沒有其他點,我們向右,依次得到2 比1高,2的糖果應該是1的基礎上加1,爲2, 5比2高,5的糖果是在2的基礎上加1,爲3。令一個凹點4, 向左,5比4高,5的糖果應該是在4的基礎上加 1,爲2,這時我們發現衝突了,從凹點1 開始,我們得到的5的糖果是3,但是從凹點 4 開始,我們得到的糖果數卻爲2 ,此時我們選擇哪個呢?當然,如果要少的,當然是2,但是它卻違反了題目中的限定條件,5如果爲2 ,就不比2的糖果數多了,所以這時我們就應該選擇最大的,這說明了什麼呢?說明從左面開始向右到 5 得到的遞增序列的長度大於從4開始向左到5得到的遞增序列。也就是說,得到的糖果數的多少,取決於所構成的連續遞增序列的長度。
class Solution:
def candy(self, A):
if len(A) == 0: return 0
candies = [1] * len(A)
#insert two guard at both bounder
#爲了便於處理凹點,我們在左右邊界各插入一個點作爲哨兵,這樣在比較的時候
#就不用額外處理邊界點了。
A.insert(0, A[0])
A.append(A[-1])
#pits 用來存儲所有的凹點下標
pits = []
for i in range(1, len(A) - 1):
if A[i] <= A[i - 1] and A[i] < A[i + 1] or \
A[i] <= A[i + 1] and A[i] < A[i - 1]:
pits.append(i)
#從左到右一次處理各個凹點
for i in pits:
# go left
j = i
while A[j - 1] > A[j]:
#因爲A數組加入了哨兵的緣故,所以A和candies的下標不是嚴格對齊的,差了一個
if candies[j - 2] < candies[j - 1] + 1:
candies[j - 2] = candies[j - 1] + 1
j -= 1
else: break
# go right
j = i
while A[j + 1] > A[j]:
if candies[j] < candies[j - 1] + 1:
candies[j] = candies[j - 1] + 1
j += 1
else: break
return sum(candies)
這裏我們需要一個額外的pits數組來存儲所有的凹點,其實通過剛纔我們的分析,另外一種實現方式已經出現了,就是從左開始,找遞增序列,然後增加糖果,對於每個數,它和左邊構成的遞增序列與從右面構成的遞增序列可能不一樣,如上例中的5,跟左邊夠成的遞增序列爲 1,2 5,長度爲3,跟右面的構成的遞增序列爲4,5,長度爲2,而5最少的糖果數是取決於最長的遞增序列的。所以我們就可以從左到右遍歷一遍,然後再從右向左遍歷一遍,取兩次遍歷的最大值。
class Solution:
def candy(self, A):
if len(A) == 0: return 0
candies = [1] * len(A)
#從左向右,按着遞增來分配糖果
for i in range(1, len(A)):
if A[i] > A[i - 1]:
candies[i] = candies[i - 1] + 1
#從右向左,按着遞增來分配糖果,並取最大值
for i in xrange(len(A) - 2, -1, -1):
if A[i] > A[i + 1] and candies[i] < candies[i + 1] + 1:
candies[i] = candies[i + 1] + 1
return sum(candies)