题目解析
这道题目要求我们为一排猫分发鱼干,并且需要满足两个条件:
- 每只猫至少分到 1 斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它应当得到比相邻的猫更多的鱼干。
从题目描述来看,我们需要用一个合适的算法来保证每只猫的鱼干数量满足以上规则,且最终返回所有猫所需要的鱼干总数。
思路分析
这道题其实是一个典型的“贪心算法”问题。我们可以将问题分解为两个阶段的扫描:
- 从左到右扫描:
首先,我们假设所有猫的初始鱼干都是 1 斤。然后,从左到右遍历猫的等级列表,对于每一只猫,如果它的等级比前一只猫高,则它需要分配的鱼干应该比前一只猫多 1 斤。这个过程确保了所有猫在相邻猫等级更高时,鱼干数量也是递增的。 - 从右到左扫描:
第二次扫描是从右到左进行的,目的是确保如果某只猫的等级比后一只猫高,它的鱼干数量仍然满足条件。如果发现当前猫比它后面的猫等级高,并且当前猫的鱼干数不满足比后面猫多 1 斤的条件,则需要调整当前猫的鱼干数。这一步确保了鱼干分配的合理性,即保证了左右两端都能满足“相邻等级高,鱼干更多”的规则。
代码解析
def solution(n, cats_levels):
# 初始化每只猫至少分配一斤鱼干
fish_dry = [1] * n
# 从左到右扫描,确保如果当前猫比前一只猫等级高,鱼干数量要更多
for i in range(1, n):
if cats_levels[i] > cats_levels[i - 1]:
fish_dry[i] = fish_dry[i - 1] + 1
# 从右到左扫描,确保如果当前猫比后一只猫等级高,鱼干数量要更多
for i in range(n - 2, -1, -1):
if cats_levels[i] > cats_levels[i + 1]:
fish_dry[i] = max(fish_dry[i], fish_dry[i + 1] + 1)
# 返回鱼干的总和
return sum(fish_dry)
代码步骤解析:
- 初始化鱼干数量: 首先,我们初始化一个
fish_dry列表,假设每只猫的鱼干数最少为 1 斤(题目要求每只猫至少得到 1 斤)。 - 左到右扫描: 从左到右扫描
cats_levels列表。如果当前猫的等级比前一只猫的等级高,那么它的鱼干数应该比前一只猫多 1 斤。因此,我们通过fish_dry[i] = fish_dry[i - 1] + 1来保证这个条件。 - 右到左扫描: 在第二次扫描中,我们从右到左遍历所有猫。这个步骤的目的是确保如果某只猫的等级高于它后面的猫,它的鱼干数应该比后面的猫多 1 斤。如果发现当前猫的鱼干数不满足条件,则更新它的鱼干数。注意,这里使用了
max(fish_dry[i], fish_dry[i + 1] + 1)来避免第一轮扫描时的调整被第二轮覆盖。 - 返回结果: 最后,我们通过
sum(fish_dry)来计算所有猫的鱼干总和并返回。
复杂度分析:
- 时间复杂度:O(n),因为我们只需要进行两次线性扫描。
- 空间复杂度:O(n),我们使用了一个
fish_dry列表来存储每只猫的鱼干数量。
知识总结
在解决这道题的过程中,我们可以总结出几个重要的知识点:
- 贪心算法:
贪心算法通过局部最优选择来得到全局最优解。这里我们通过两次扫描,确保了每只猫在左右两侧的鱼干数量都满足“比相邻猫多”的条件。这是一个典型的贪心策略:从局部保证正确性,然后通过两次遍历来调整和优化。 - 双向扫描:
双向扫描是一种非常有用的技巧,可以有效地解决这类具有局部优化问题的题目。通过一次从左到右扫描和一次从右到左扫描,我们可以同时考虑左边和右边的相对关系,确保鱼干的分配满足条件。 - 动态调整:
在第二次扫描时,我们通过动态调整猫的鱼干数量来确保满足条件,而不是直接依赖第一次扫描的结果。这种动态调整的思想在很多优化问题中都有应用。
给其他入门同学的学习建议
- 理解贪心算法的本质:
贪心算法并不总是适用于所有问题,关键在于判断是否可以通过局部最优解得到全局最优解。在这道题中,通过两次扫描,局部最优(左右两端的条件)合并后得到了全局最优解。 - 练习双向扫描的技巧:
双向扫描是一个非常实用的技巧,尤其适用于处理依赖于前后元素关系的题目。通过反向扫描,可以避免单次扫描时遗漏某些边界条件。 - 逐步思考和调试:
这道题虽然简单,但在实际解题过程中可能会遇到一些边界条件问题,比如相同等级的猫鱼干数应该相等,或者当猫的等级是递增或递减时的特殊情况。因此,在写代码时,建议多画出几种情况的示意图,以帮助理清思路。 - 不断积累题目经验:
刷题时不要只看解答,应该思考每一道题目的思路,尤其是如何从具体问题抽象出适合的算法。通过不断积累不同类型的问题经验,可以提高算法思维的灵活性和解决问题的效率。
结语
这道题目涉及的鱼干分配问题本质上是一个贪心问题,利用双向扫描来调整鱼干数量是解决这类问题的有效方法。通过这道题目,我们不仅可以巩固贪心算法的基本思路,还能进一步理解如何处理相邻元素之间的关系。希望大家在今后的学习中,能多加练习,提升解决实际问题的能力。