问题描述
在猫星球上,小R负责给一行排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:
- 每只猫至少得到一斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。
小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干**。**
解题思路
这个问题通过贪心算法和两次遍历来解决,步骤如下:
(1)初始化鱼干分布
假设我们有 n 只猫,首先,我们可以创建一个长度为 n 的数组 fish,初始化为每只猫至少1斤鱼干,即 fish[i] = 1,或者,始化鱼干的总量为每只猫至少得到的鱼干,即fish = [1]*n。
(2)从左到右的遍历
遍历一遍猫队列,如果当前猫的等级比前一只猫高,那么它应该获得比前一只猫更多的鱼干。所以在遍历时,如果发现 level[i] > level[i-1],我们就更新 fish[i] = fish[i-1] + 1。
(3)从右到左的遍历
进行第二次遍历,确保等级高的猫得到的鱼干比它右边的猫多。如果当前猫的等级比右侧猫高,并且它的鱼干数不比右侧猫多,我们就更新 fish[i] = max(fish[i], fish[i+1] + 1)。max 这里是为了避免第二次遍历影响到第一次遍历时的调整。
(4)计算鱼干总量
最后,所有猫的鱼干量之和就是我们需要准备的最少鱼干量,即sum(fish)。
代码详解
def solution(n, cats_levels):
# Please write your code here
if n == 0:
return 0
# 初始化鱼干的总量为每只猫至少得到的鱼干
fish = [1] * n
# 从左到右遍历,确保等级高的猫得到的鱼干比它左边的猫多
for i in range(1, n):
if cats_levels[i] > cats_levels[i - 1]:
fish[i] = fish[i - 1] + 1
# 从右到左遍历,确保等级高的猫得到的鱼干比它右边的猫多
for i in range(n - 2, -1, -1):
if cats_levels[i] > cats_levels[i + 1]:
fish[i] = max(fish[i], fish[i + 1] + 1)
# 计算所需的鱼干总量
return sum(fish)
if __name__ == "__main__":
# You can add more test cases here
cats_levels1 = [1, 2, 2]
cats_levels2 = [6, 5, 4, 3, 2, 16]
cats_levels3 = [1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4]
print(solution(3, cats_levels1) == 4)
print(solution(6, cats_levels2) == 17)
print(solution(20, cats_levels3) == 35)
总结
这个问题是一个典型的贪心算法应用场景。通过两次遍历来保证猫的鱼干分配满足条件:每只猫至少有一斤鱼干,并且更高等级的猫应该得到更多鱼干。这让我理解了如何通过局部最优(当前猫的鱼干分配)来实现全局最优解。在这个问题中,解法先从左到右遍历一次,再从右到左遍历一次来调整鱼干数量。这让我明白了在某些问题中,多个遍历可能是必要的,每一次遍历都是对上一轮结果的进一步优化。同时要考虑到边界条件,例如,在从右到左遍历时,需要确保不会超出数组的范围。其次,通过使用一个辅助数组 fish 来记录每只猫的鱼干数,让我理解了数组和比较的使用。