【leetcode】Candy(python)

題目要求比其高的鄰居要比本身的獎勵多,那麼最少也要多一個,所有我們可以找到所有的凹點,凹點如下三種情形。


找到所有的凹點後,我們就可以從凹點處開始向左右兩個方向依次查找遞增序列,其中每個高的都要比相鄰的矮的多一個,比如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)  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章