AI刷题中档题 贪心猫的鱼干大分配 解答 | 豆包MarsCode AI刷题

61 阅读5分钟

贪心猫的鱼干大分配

问题描述

在猫星球上,每只猫的等级决定了它应该获得的鱼干斤数。为了保证公平,分发鱼干需遵守以下规则:

  1. 每只猫至少得到 1斤鱼干
  2. 如果一只猫的等级高于它相邻的猫,它应该比相邻的猫得到 更多的鱼干

目标是计算出,为满足以上规则所需的 最少鱼干总量


问题分析

为了实现规则并计算最少的鱼干分发总量,需要处理以下几个关键问题:

  1. 相邻比较:
    确保每只猫的鱼干分配满足与相邻猫的等级差异。

  2. 最小分配原则:
    每只猫的鱼干分配不能低于 1,但也不能超出必要值以节省总鱼干量。

  3. 顺序处理:

    • 需要从左到右和从右到左两次扫描,分别处理每只猫与左侧和右侧猫的关系。

算法设计

为了解决问题,我们可以分两次遍历猫的等级列表:

  1. 从左向右扫描:

    • 检查每只猫与左侧相邻猫的等级关系。
    • 如果当前猫等级高于左侧猫,则当前猫的鱼干比左侧猫多 1。
  2. 从右向左扫描:

    • 检查每只猫与右侧相邻猫的等级关系。
    • 如果当前猫等级高于右侧猫,更新当前猫的鱼干值,确保满足右侧等级关系。
  3. 计算总和:

    • 两次扫描后,数组中的每个值表示每只猫的最终鱼干分配,直接求和即可。

关键逻辑详解

  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)。

  2. 从右向左遍历

    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() 函数。
  3. 计算总和

    return sum(fish)
    
    • 遍历完成后,fish 数组中存储的是满足所有规则的鱼干分配量,直接求和得到最少总量。

示例分析

示例输入:

cats_levels = [1, 2, 2]
  1. 初始化

    fish = [1, 1, 1]  # 每只猫至少分 1斤
    
  2. 从左向右扫描

    • 比较 cats_levels[1]cats_levels[0]

      • 2 > 1,所以 fish[1] = fish[0] + 1 = 2
    • 比较 cats_levels[2]cats_levels[1]

      • 2 == 2,不变。

    结果:

    fish = [1, 2, 1]
    
  3. 从右向左扫描

    • 比较 cats_levels[1]cats_levels[2]

      • 2 > 2,不变。
    • 比较 cats_levels[0]cats_levels[1]

      • 1 < 2,不变。

    结果:

    fish = [1, 2, 1]
    
  4. 计算总和

    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]

  2. 从左到右扫描:

    • 猫 1 比猫 0 等级高,鱼干调整为 [1, 2, 1]
  3. 从右到左扫描:

    • 无需调整。
  4. 总鱼干:1 + 2 + 1 = 4
    输出:4

样例2:

输入:n = 6, cats_levels = [6, 5, 4, 3, 2, 16]

  1. 初始化鱼干分配:[1, 1, 1, 1, 1, 1]

  2. 从左到右扫描:

    • 猫 5 比猫 4 等级高,鱼干调整为 [1, 1, 1, 1, 1, 2]
  3. 从右到左扫描:

    • 猫 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. 总鱼干: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, ..., 1](共20个1)

  2. 从左到右扫描:

    • 猫 1 比猫 0 高,调整。
    • 猫 3 比猫 2 高,调整。
    • 猫 5 比猫 4 高,调整。...依此类推。
  3. 从右到左扫描:

    • 猫 18 比猫 19 高,调整。
    • 猫 17 比猫 18 高,调整。...依此类推。
  4. 最终分配鱼干数组:[1, 2, 1, 2, 1, 6, 1, 2, 3, 2, 1, 1, 2, 3, 1, 2, 1, 3, 2, 1]

  5. 总鱼干:35
    输出:35


复杂度分析

  1. 时间复杂度:

    • 左右两次遍历,每次 O(n)。总复杂度为 O(n)。
  2. 空间复杂度:

    • 额外的鱼干分配数组,空间复杂度为 O(n)。

总结

该算法通过两次遍历的方式,高效地解决了鱼干分配问题,既保证了公平性,也最小化了总鱼干量的使用。该方法易于理解和实现,适用于实际场景中类似的分配问题