贪心猫的鱼干大分配:问题解析与代码详解
问题描述
在猫星球上,小R负责给排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。具体规则如下:
- 每只猫至少得到一斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。
我们的目标是计算小R至少需要准备多少斤鱼干,以公平地满足所有猫的等级差异。
思路解析
这个问题可以通过贪心算法来解决。我们需要确保在分配鱼干时,满足以下两个条件:
- 每只猫至少获得 1 斤鱼干。
- 对于每只猫,如果它的等级高于相邻的猫,则它的鱼干数量必须比相邻猫的鱼干数量多。
步骤
-
初始化鱼干数量:创建一个与猫的数量相同的数组
candies,并将每个元素初始化为 1,表示每只猫至少获得 1 斤鱼干。 -
从左到右遍历:遍历猫的等级列表,如果当前猫的等级高于前一只猫,则将当前猫的鱼干数量设置为前一只猫的鱼干数量加 1。
-
从右到左遍历:再从右向左遍历猫的等级列表,如果当前猫的等级高于后一只猫,则将当前猫的鱼干数量设置为当前值和后一只猫的鱼干数量加 1 的最大值。
-
计算总鱼干数量:最后,将
candies数组中的所有元素相加,得到总的鱼干数量。
图解
假设我们有 5 只猫,等级为 [1, 3, 2, 4, 3]。我们可以用以下步骤进行分配:
- 初始化
candies数组为[1, 1, 1, 1, 1]。 - 从左到右遍历:
- 对于猫 2(等级 3),比猫 1(等级 1)高,
candies更新为[1, 2, 1, 1, 1]。 - 对于猫 3(等级 2),不高于猫 2,保持不变。
- 对于猫 4(等级 4),比猫 3(等级 2)高,
candies更新为[1, 2, 1, 2, 1]。 - 对于猫 5(等级 3),不高于猫 4,保持不变。
- 对于猫 2(等级 3),比猫 1(等级 1)高,
- 从右到左遍历:
- 对于猫 4(等级 4),比猫 5(等级 3)高,
candies更新为[1, 2, 1, 2, 2]。 - 对于猫 3(等级 2),不高于猫 4,保持不变。
- 对于猫 2(等级 3),比猫 1(等级 1)高,保持不变。
- 对于猫 4(等级 4),比猫 5(等级 3)高,
最终,candies 数组为 [1, 2, 1, 2, 2],总鱼干数量为 8。
代码详解
以下是实现上述逻辑的代码:
def solution(n, cats_levels):
# 初始化每只猫的鱼干数量
candies = [1] * n
# 从左到右遍历
for i in range(1, n):
if cats_levels[i] > cats_levels[i - 1]:
candies[i] = candies[i - 1] + 1
# 从右到左遍历
for i in range(n - 2, -1, -1):
if cats_levels[i] > cats_levels[i + 1]:
candies[i] = max(candies[i], candies[i + 1] + 1)
# 计算总鱼干数量
return sum(candies)
if __name__ == "__main__":
# 测试样例
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) # 输出: True
print(solution(6, cats_levels2) == 17) # 输出: True
print(solution(20, cats_levels3) == 35) # 输出: True
代码分析
- 初始化:
candies = [1] * n确保每只猫至少获得 1 斤鱼干。 - 左到右遍历:通过
for i in range(1, n)遍历每只猫,检查相邻猫咪的等级并更新鱼干数量。 - 右到左遍历:通过
for i in range(n - 2, -1, -1)进行反向遍历,确保反向条件也得到满足。 - 总和计算:
return sum(candies)返回所有猫咪鱼干的总和。
复杂度分析
- 时间复杂度:O(n),因为我们只遍历了数组两次。
- 空间复杂度:O(n),我们使用了一个额外的数组
candies来存储每只猫的鱼干数量。
总结
通过贪心算法,我们能够高效地解决猫咪鱼干分配的问题。通过两次遍历,我们能够确保每只猫都获得了合适的鱼干,满足了等级的要求。这种方法不仅简单直观,而且在实际应用中也非常高效。 在解决“贪心猫的鱼干大分配”问题的过程中,我深刻体会到贪心算法的有效性。通过两次遍历(左到右和右到左),我们确保了每只猫在满足相邻猫鱼干分配规则的情况下,尽量减少总鱼干数量。这种分步思考的方式让我清晰理解了每一步的影响。
在编写代码时,我注重可读性和维护性,合理命名变量并添加注释,确保代码易于理解。同时,我重视边界条件的处理,避免潜在的错误。在完成后,我进行了复杂度分析,确认算法在大规模数据下的表现。
通过这个问题,我意识到理论知识与实践能力同样重要,今后我将继续通过解决各种算法题目来巩固自己的能力,提升编程水平。这个过程让我更加自信地面对未来更复杂的挑战。