Skip to content

Commit 8fb5124

Browse files
authored
Create 135._Candy.md
1 parent 5898383 commit 8fb5124

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# 135. Candy
2+
3+
**<font color=red>难度: Hard</font>**
4+
5+
## 刷题内容
6+
7+
> 原题连接
8+
9+
* https://leetcode.com/problems/candy/
10+
11+
> 内容描述
12+
13+
```
14+
15+
There are N children standing in a line. Each child is assigned a rating value.
16+
17+
You are giving candies to these children subjected to the following requirements:
18+
19+
Each child must have at least one candy.
20+
Children with a higher rating get more candies than their neighbors.
21+
What is the minimum candies you must give?
22+
23+
Example 1:
24+
25+
Input: [1,0,2]
26+
Output: 5
27+
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
28+
Example 2:
29+
30+
Input: [1,2,2]
31+
Output: 4
32+
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
33+
The third child gets 1 candy because it satisfies the above two conditions.
34+
```
35+
36+
## 解题方案
37+
38+
> 思路 1
39+
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
40+
41+
42+
43+
- 首先我们从左往右边看,如果当前child的rating比它左边child的rating大,那么当前child分的candy肯定要比它左边多1
44+
- 然后从右往左边看,如果当前child的rating比它右边child的rating大,那么当前child分的candy肯定要比它右边多1
45+
46+
我们知道这两种情况我们都必须满足,所以最后我们取两者中的大者(这样才能同时满足两种情况),beats 24.83%
47+
48+
```python
49+
class Solution:
50+
def candy(self, ratings):
51+
"""
52+
:type ratings: List[int]
53+
:rtype: int
54+
"""
55+
left2right = [1] * len(ratings)
56+
right2left = [1] * len(ratings)
57+
for i in range(1, len(ratings)):
58+
if ratings[i] > ratings[i-1]:
59+
left2right[i] = left2right[i-1] + 1
60+
for i in range(len(ratings)-2, -1, -1):
61+
if ratings[i] > ratings[i+1]:
62+
right2left[i] = right2left[i+1] + 1
63+
res = 0
64+
for i in range(len(ratings)):
65+
res += max(left2right[i], right2left[i])
66+
return res
67+
```
68+
69+
> 思路 2
70+
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******
71+
72+
刚才用了2个array,其实我们可以只用一个array, beats 28.77%
73+
74+
```python
75+
class Solution:
76+
def candy(self, ratings):
77+
"""
78+
:type ratings: List[int]
79+
:rtype: int
80+
"""
81+
res = [1] * len(ratings) # also compatable with [] input
82+
# left scan
83+
for i in range(1, len(ratings)):
84+
if ratings[i] > ratings[i-1]:
85+
res[i] = res[i-1] + 1
86+
# right scan
87+
for i in range(len(ratings)-2, -1, -1):
88+
if ratings[i] > ratings[i+1]:
89+
res[i] = max(res[i+1]+1, res[i])
90+
return sum(res)
91+
```
92+
93+
94+
> 思路 3
95+
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
96+
97+
其实我们还有另外一种思路,可以将空间降到O(1)
98+
99+
假设:
100+
```
101+
input: [2, 4, 6, 8, 7, 6, 5, 4, 3, 2, 7, 8, 9, 8, 7, 6, 5, 4, 3]
102+
index: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19]
103+
104+
```
105+
106+
我们先直接给第一个孩子1颗candy,然后继续往下遍历,我们发现第2个孩子的rating比第一个孩子的多,于是我们给第二个孩子2颗candy,
107+
以此类推,第3个孩子3颗candy,第4个孩子4颗candy,这时候我们发现第5个孩子的rating比第4个孩子的rating要小,
108+
所以第5个孩子的candy肯定要比第4个孩子的少才行,但是不能直接给第5个孩子1颗candy这么简单,因为说不定后面孩子的rating比第5个孩子更小呢?
109+
如果第5个孩子只有1颗candy,后面的孩子岂不是没有candy了?这不符合题目要求,所以我们暂时继续走下去,我们发现一共降序走了6步,此时来到了第11个孩子,
110+
rating终于又变成升序了,这时候我们知道了,第5个孩子最少需要给6颗candy了,然后第6,7,8,9,10个孩子依次给5,4,3,2,1颗candy,总数就是6*(1+6)/2
111+
但是问题来了,第5个孩子给了6颗candy,第4个孩子应该要比第5个孩子的candy更多呀, 于是我们补给第4个孩子3颗candy,此时第4个孩子有7颗candy
112+
(比第5个孩子的6颗多,符合题目要求)。继续走下去,第11个孩子给2颗candy,第12个孩子给3颗candy,第13个孩子给4颗candy,接下来又是降序了,
113+
又是降序走了6步,一样的原理,第14,15,16,17,18,19个孩子分别给6,5,4,3,2,1颗candy,发现第13个孩子需要补3颗candy(现在7颗candy)
114+
115+
于是我们的candy的总和为
116+
117+
```
118+
input: [2, 4, 6, 8, 7, 6, 5, 4, 3, 2, 7, 8, 9, 8, 7, 6, 5, 4, 3]
119+
candy: [1, 2, 3, 7, 6, 5, 4, 3, 2, 1, 2, 3, 7, 6, 5, 4, 3, 2, 1]
120+
index: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19]
121+
122+
一共67颗candy
123+
```
124+
125+
编码实现, beats 59.40%
126+
127+
```python
128+
class Solution:
129+
def candy(self, ratings):
130+
"""
131+
:type ratings: List[int]
132+
:rtype: int
133+
"""
134+
if not ratings:
135+
return 0
136+
res, prev, desc_cnt = 1, 1, 0
137+
for i in range(1, len(ratings)):
138+
if ratings[i] >= ratings[i-1]:
139+
if desc_cnt > 0:
140+
res += desc_cnt * (desc_cnt + 1) / 2 # arithmetic progression
141+
if desc_cnt >= prev:
142+
res += desc_cnt - prev + 1
143+
desc_cnt = 0
144+
prev = 1
145+
# 当前child的rating和它左边child的rating一样,直接给1颗candy就满足了,否则需要给prev+1颗candy
146+
prev = 1 if ratings[i] == ratings[i-1] else prev + 1
147+
res += prev
148+
else:
149+
desc_cnt += 1
150+
if desc_cnt > 0: # if we were descending at the end
151+
res += desc_cnt * (desc_cnt + 1) / 2 # arithmetic progression
152+
if desc_cnt >= prev:
153+
res += desc_cnt - prev + 1
154+
return int(res)
155+
```
156+
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+
174+
175+
176+
177+
178+
179+
180+
181+
182+
183+
184+
185+
186+
187+
188+
189+
190+
191+

0 commit comments

Comments
 (0)