贪心猫的鱼干大分配
问题描述
在猫星球上,每只猫的等级决定了它应该获得的鱼干斤数。为了保证公平,分发鱼干需遵守以下规则:
- 每只猫至少得到 1斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它应该比相邻的猫得到 更多的鱼干。
目标是计算出,为满足以上规则所需的 最少鱼干总量。
问题分析
为了实现规则并计算最少的鱼干分发总量,需要处理以下几个关键问题:
-
相邻比较:
确保每只猫的鱼干分配满足与相邻猫的等级差异。 -
最小分配原则:
每只猫的鱼干分配不能低于 1,但也不能超出必要值以节省总鱼干量。 -
顺序处理:
- 需要从左到右和从右到左两次扫描,分别处理每只猫与左侧和右侧猫的关系。
算法设计
为了解决问题,我们可以分两次遍历猫的等级列表:
-
从左向右扫描:
- 检查每只猫与左侧相邻猫的等级关系。
- 如果当前猫等级高于左侧猫,则当前猫的鱼干比左侧猫多 1。
-
从右向左扫描:
- 检查每只猫与右侧相邻猫的等级关系。
- 如果当前猫等级高于右侧猫,更新当前猫的鱼干值,确保满足右侧等级关系。
-
计算总和:
- 两次扫描后,数组中的每个值表示每只猫的最终鱼干分配,直接求和即可。
关键逻辑详解
-
从左向右遍历
for i in range(1, n): if cats_levels[i] > cats_levels[i - 1]: fish[i] = fish[i - 1] + 1-
目标:处理左侧关系,确保等级更高的猫获得更多鱼干。
-
逻辑:
-
如果当前猫的等级
cats_levels[i]高于左侧猫cats_levels[i - 1]:- 当前猫的鱼干
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)-
目标:处理右侧关系,确保等级更高的猫获得更多鱼干。
-
逻辑:
-
如果当前猫的等级
cats_levels[i]高于右侧猫cats_levels[i + 1]:- 当前猫的鱼干
fish[i]应至少比右侧猫多 1。 - 同时确保
fish[i]保持与左侧遍历结果一致,使用max()函数。
- 当前猫的鱼干
-
-
-
计算总和
return sum(fish)- 遍历完成后,
fish数组中存储的是满足所有规则的鱼干分配量,直接求和得到最少总量。
- 遍历完成后,
示例分析
示例输入:
cats_levels = [1, 2, 2]
-
初始化
fish = [1, 1, 1] # 每只猫至少分 1斤 -
从左向右扫描
-
比较
cats_levels[1]和cats_levels[0]:- 2 > 1,所以
fish[1] = fish[0] + 1 = 2。
- 2 > 1,所以
-
比较
cats_levels[2]和cats_levels[1]:- 2 == 2,不变。
结果:
fish = [1, 2, 1] -
-
从右向左扫描
-
比较
cats_levels[1]和cats_levels[2]:- 2 > 2,不变。
-
比较
cats_levels[0]和cats_levels[1]:- 1 < 2,不变。
结果:
fish = [1, 2, 1] -
-
计算总和
sum(fish) = 1 + 2 + 1 = 4
代码实现
以下是基于上述思路的代码实现:
from typing import Concatenate
def solution(n, cats_levels):
# Please write your code here
fish = [0 for _ in range(n)]
cats = [[index,val] for index,val in enumerate(cats_levels)]
cats.sort(key = lambda x: x[1])
for x in cats:
index = x[0]
level = x[1]
leftindex,rightindex = 0,n-1
if index > 0:
leftindex = index-1
if index < n-1:
rightindex = index+1
leftlevel,rightlevel = cats_levels[leftindex],cats_levels[rightindex]
if level > leftlevel and level > rightlevel:
fish[index] = max(fish[leftindex],fish[rightindex])+1
elif level > leftlevel:
fish[index] = fish[leftindex] + 1
elif level > rightlevel:
fish[index] = fish[rightindex] + 1
else:
fish[index] = 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)
测试样例解析
样例1:
输入:n = 3, cats_levels = [1, 2, 2]
-
初始化鱼干分配:
[1, 1, 1] -
从左到右扫描:
- 猫 1 比猫 0 等级高,鱼干调整为
[1, 2, 1]
- 猫 1 比猫 0 等级高,鱼干调整为
-
从右到左扫描:
- 无需调整。
-
总鱼干:
1 + 2 + 1 = 4
输出:4
样例2:
输入:n = 6, cats_levels = [6, 5, 4, 3, 2, 16]
-
初始化鱼干分配:
[1, 1, 1, 1, 1, 1] -
从左到右扫描:
- 猫 5 比猫 4 等级高,鱼干调整为
[1, 1, 1, 1, 1, 2]
- 猫 5 比猫 4 等级高,鱼干调整为
-
从右到左扫描:
- 猫 4 比猫 3 等级高,调整为
[1, 1, 1, 1, 2, 2] - 猫 3 比猫 2 等级高,调整为
[1, 1, 1, 2, 2, 2] - 猫 2 比猫 1 等级高,调整为
[1, 1, 2, 2, 2, 2] - 猫 1 比猫 0 等级高,调整为
[1, 2, 2, 2, 2, 2]
- 猫 4 比猫 3 等级高,调整为
-
总鱼干:
1 + 2 + 2 + 2 + 2 + 2 = 17
输出:17
样例3:
输入:n = 20, cats_levels = [1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4]
-
初始化鱼干分配:
[1, 1, ..., 1](共20个1) -
从左到右扫描:
- 猫 1 比猫 0 高,调整。
- 猫 3 比猫 2 高,调整。
- 猫 5 比猫 4 高,调整。...依此类推。
-
从右到左扫描:
- 猫 18 比猫 19 高,调整。
- 猫 17 比猫 18 高,调整。...依此类推。
-
最终分配鱼干数组:
[1, 2, 1, 2, 1, 6, 1, 2, 3, 2, 1, 1, 2, 3, 1, 2, 1, 3, 2, 1] -
总鱼干:
35
输出:35
复杂度分析
-
时间复杂度:
- 左右两次遍历,每次 O(n)。总复杂度为 O(n)。
-
空间复杂度:
- 额外的鱼干分配数组,空间复杂度为 O(n)。
总结
该算法通过两次遍历的方式,高效地解决了鱼干分配问题,既保证了公平性,也最小化了总鱼干量的使用。该方法易于理解和实现,适用于实际场景中类似的分配问题