給 n 個小朋友分糖,每個人至少有一顆糖。並且有乙個rating
陣列,如果小朋友的rating
比它旁邊小朋友的rating
大(不包括等於),那麼他必須要比對應小朋友的糖多。問至少需要分配多少顆糖。
用-
表示糖,舉幾個例子。
102
----
-總共就需要 5 顆糖。12
2---
-總共就需要 4 顆糖。
根據題目,首先每個小朋友會至少有乙個糖。
如果當前小朋友的rating
比後乙個小朋友的小,那麼後乙個小朋友的糖肯定是當前小朋友的糖加1
。
比如ration = [ 5, 6, 7]
,那麼三個小朋友的糖就依次是1 2 3
。
如果當前小朋友的rating
比後乙個小朋友的大,那麼理論上當前小朋友的糖要比後乙個的小朋友的糖多,但此時後乙個小朋友的糖還沒有確定,怎麼辦呢?
參考 32題 的解法五,利用正著遍歷,再倒著遍歷的思想。
首先我們正著遍歷一次,只考慮當前小朋友的rating
比後乙個小朋友的小的情況。
接著再倒著遍歷依次,繼續考慮當前小朋友的rating
比後乙個小朋友的小的情況。因為之前已經更新過一次糖果了,此時後乙個小朋友的糖如果已經比當前小朋友的糖多了,就不需要進行更新了。
舉個例子
初始化每人乙個糖12
3214
----
--.
只考慮當前小朋友的 rating 比後乙個小朋友的小的情況,後乙個小朋友的糖是當前小朋友的糖加 1。
1<21
2321
4---
----
2<31
2321
4---
----
--3>
2 不考慮
2>
1 不考慮
1<41
2321
4---
----
---
倒過來重新進行
繼續考慮當前小朋友的 rating 比後乙個小朋友的小的情況。此時後乙個小朋友的糖如果已經比當前小朋友的糖多了,就不需要進行更新。41
2321
----
----
--4>
1 不考慮
1<24
1232
1---
----
----
2<
3,3 的糖果已經比 2 的多了,不需要考慮
3>
2,不考慮
2>
1,不考慮
所以最終的糖的數量就是上邊的 - 的和。
**的話,我們用乙個candies
陣列儲存當前的分配情況。
public
intcandy
(int
ratings)
//正著進行
for(
int i =
0; i < n -
1; i++)}
//倒著進行
//下標順序就變成了 i i-1 i-2 i-3 ... 0
//當前就是第 i 個,後乙個就是第 i - 1 個
for(
int i = n -
1; i >
0; i--)}
}//計算糖果總和
int sum =0;
for(
int i =
0; i < n; i++
)return sum;
}
時間複雜度:o(n)。
空間複雜度:o(n)。
參考 這裡。
解法一中,考慮到
如果當前小朋友的rating
比後乙個小朋友的大,那麼理論上當前小朋友的糖要比後乙個的小朋友的糖多,但此時後乙個小朋友的糖還沒有確定,怎麼辦呢?
之前採用了倒著遍歷一次的方式進行了解決,這裡再考慮另外一種解法。
考慮下邊的情況。
對於第2
個rating 4
,它比後乙個rating
要大,所以要取決於再後邊的rating
,一直走到2
,也就是山底,此時對應的糖果數是1
,然後往後走,走回山頂,糖果數一次加1
,也就是到rating 4
時,糖果數就是3
了。
再一般化,山頂的糖果數就等於從左邊的山底或右邊的山底依次加1
。
所以我們的演算法只需要記錄山頂,然後再記錄下坡的高度,下坡的高度剛好是乙個等差序列可以直接用公式求和。而山頂的糖果數,取決於左邊山底到山頂和右邊山底到山頂的哪個高度大。
而產生山底可以有兩種情況,一種是rating
產生了增加,如上圖。還有一種就是rating
不再降低,而是持平。
知道了上邊的想法,基本上就可以寫**了,每個人寫出來的應該都不一樣,在discuss
區也看到了很多不同的寫法,下邊說一下我的思路。
抽象出四種情況,這裡的高度不是rating
進行相減,而是從山底的rating
到山頂的rating
經過的次數。
左邊山底到山頂的高度大,並且右邊山底後繼續增加。
左邊山底到山頂的高度大,並且右邊山底是平坡。
右邊山底到山頂的高度大,並且右邊山底後繼續增加。
右邊山底到山頂的高度大,並且右邊山底是平坡。
有了這四種情況就可以寫**了。
我們用total
變數記錄糖果總和,pre
變數記錄前乙個小朋友的糖果數。如果當前的rating
比前乙個的rating
大,那麼說明在走上坡,可以把前乙個小朋友的糖果數加到total
中,並且更新pre
為當前小朋友的糖果數。
如果當前的rating
比前乙個的rating
小,說明開始走下坡,用down
變數記錄連續多少次下降,此時的pre
記錄的就是從左邊山底到山底的高度。當出現平坡或上坡的時候,將所有的下坡的糖果數利用等差公式計算。此外根據pre
和down
決定山頂的糖果數。
根據當前是上坡還是平坡,來更新pre
。
大框架就是上邊的想法了,還有一些邊界需要考慮一下,看一下**。
public
intcandy
(int
ratings)
else
//當前是上坡,對應情況 1 或者 3
//更新 pre 等於 2
if(ratings[i]
> ratings[i -1]
)else
down =0;
//之前沒有出現過下坡
}else
else}}
else
}//判斷是否有下坡
if(down >0)
else
//將最後乙個小朋友的糖果計算
}else
return total;
}//等差數列求和
private
intcount
(int n)
這個演算法相對於解法一的好處就是將空間複雜度從o(n)
優化到了o(1)
。
解法一雖然空間複雜度大一些,但是很好理解,正著遍歷,倒著遍歷的思想,每次遇到都印象深刻。解法二主要是對問題進行深入考慮,雖然麻煩些,但空間複雜度確實優化了。
更多詳細通俗題解詳見 leetcode.wang 。
力扣刷題筆記 135 分發糖果
題目 135.分發糖果 老師想給孩子們分發糖果,有 n 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。你需要按照以下要求,幫助老師給這些孩子分發糖果 每個孩子至少分配到 1 個糖果。相鄰的孩子中,評分高的孩子必須獲得更多的糖果。那麼這樣下來,老師至少需要準備多少顆糖果呢?示例 1 ...
LeetCode 135 分發糖果
老師想給孩子們分發糖果,有 n 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。你需要按照以下要求,幫助老師給這些孩子分發糖果 每個孩子至少分配到 1 個糖果。相鄰的孩子中,評分高的孩子必須獲得更多的糖果。那麼這樣下來,老師至少需要準備多少顆糖果呢?示例 1 輸入 1,0,2 輸出 ...
leetcode135 分發糖果
一道很有意思的題目,難度級別為 困難。題目是這樣的的 老師想給孩子們分發糖果,有 n 個孩子站成了一條直線,老師會根據每個孩子的表現,預先給他們評分。你需要按照以下要求,幫助老師給這些孩子分發糖果 每個孩子至少分配到 1 個糖果。相鄰的孩子中,評分高的孩子必須獲得更多的糖果。那麼這樣下來,老師至少需...