题目
在【六.一】儿童节刷的这道题,看到题目时两眼放光(谁还不是个可爱的小朋友呢!)
题目解题不难,是非常纯粹的一道数学应用题,关键是要把题目读懂,从故事中提炼出数学问题。
限制条件:
- 从第 0 天开始吃糖,注意是 0
- 吃 i 类型的糖之前,必须把 0 到 i - 1 类型的糖全部吃完
- 每天最少吃 1 颗糖,最多吃 D a i l y C a p i DailyCap_i DailyCapi 颗糖
提炼出的数学问题其实是:
- The query is true if and only if your favorite day is in between the earliest and latest possible days to eat your favorite candy
- To get the earliest day, you need to eat dailyCap candies every day
- To get the latest day, you need to eat 1 candy every day
- The latest possible day is the total number of candies with a smaller type plus the number of your favorite candy minus 1(从 day 0 开始吃的)
- The earliest possible day that you can eat your favorite candy is the total number of candies with a smaller type divided by dailyCap
解题
class Solution:
def canEat(self, candiesCount: List[int], queries: List[List[int]]) -> List[bool]:
res = []
candiesCount = list(accumulate(candiesCount))
#for i in range(1, len(candiesCount)):
# candiesCount[i] = candiesCount[i] + candiesCount[i-1]
for CandyType, CandyDay, CandyCap in queries:
LastDay = candiesCount[CandyType] - 1
if CandyType == 0: # 第 0 天就可吃到 Type 0 糖果
FirstDay = 0
else:
FirstDay = candiesCount[CandyType-1] // CandyCap
if CandyDay <= LastDay and CandyDay >= FirstDay:
res.append(True)
else:
res.append(False)
return res
上面解题是从 favoriteday 是否落在 [firstday, lastday] 入手的,官方解题是算糖果的数量:
class Solution:
def canEat(self, candiesCount: List[int], queries: List[List[int]]) -> List[bool]:
# 前缀和
total = list(accumulate(candiesCount))
ans = list()
for favoriteType, favoriteDay, dailyCap in queries:
x1 = favoriteDay + 1
y1 = (favoriteDay + 1) * dailyCap
x2 = 1 if favoriteType == 0 else total[favoriteType - 1] + 1
y2 = total[favoriteType]
ans.append(not(x1 > y2 or y1 < x2))
return ans
时间复杂度: O ( n + q ) O(n+q) O(n+q) 其中 n n n 和 q q q 分别是数组 candiesCount 和 queries 的长度。我们需要 O ( n ) O(n) O(n) 的时间计算前缀和, O ( q ) O(q) O(q) 的时间得到所有询问的结果。
空间复杂度: O ( n ) O(n) O(n),即为存储前缀和数组需要的空间。注意返回值不计入空间复杂度。