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

105 阅读4分钟

问题

问题描述

在猫星球上,小R负责给一行排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:

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

小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干。


测试样例

样例1:

输入:n = 3, cats_levels = [1, 2, 2] 输出:4

样例2:

输入:n = 6, cats_levels = [6, 5, 4, 3, 2, 16] 输出: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] 输出:35

解题思路

解决方法:两次遍历

如果一下子想要确定这只猫要分配多少鱼干比较困难的话,我们可以先将这个问题拆解为两个问题。

问题1规则如下

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

那很简单,我们只要从左往右遍历,我们就能知道这只猫与左边相邻的猫之间的等级大小关系,如果这只猫等级更高,只要比左边相邻的猫获得的鱼干多1即可。

 for (int i = 1; i < len; i++) 
     if (catsLevels[i] > catsLevels[i-1]) fish[i] = fish[i-1] + 1;

问题2规则如下

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

那很简单,我们只要从右往左遍历,我们就能知道这只猫与右边相邻的猫之间的等级大小关系,如果这只猫等级更高,只要比右边相邻的猫获得的鱼干多1即可。

 for (int i = len-2; i >= 0; i--) 
     if (catsLevels[i] > catsLevels[i+1] && fish[i] <= fish[i+1]) fish[i] = fish[i+1] + 1;

问题合并(原题)

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

只需要简单的将上面两个问题的解法组合在一起即可。

 for (int i = 1; i < len; i++) 
     if (catsLevels[i] > catsLevels[i-1]) fish[i] = fish[i-1] + 1;
 for (int i = len-2; i >= 0; i--) 
     if (catsLevels[i] > catsLevels[i+1] && fish[i] <= fish[i+1]) fish[i] = fish[i+1] + 1;

问:第二次遍历会影响到第一次吗?

不会

在第二次遍历(从右到左)中,只有在满足以下条件时才会更新 fish[i]

  • 当前猫的等级 catsLevels[i] 高于右边的猫 catsLevels[i + 1]
  • 当前猫的鱼干数量 fish[i] 小于或等于右边猫的鱼干数量 fish[i + 1]

这意味着,只有当 fish[i] <= fish[i + 1] 时,才会修改 fish[i]。然而,这种情况下,fish[i] 的值会被调整为 fish[i + 1] + 1。这样做不会影响到 fish[i] 和左边相邻猫的关系,因为:

  • 如果 fish[i] 在第一次遍历中已经比 fish[i - 1](即 fish[i] > fish[i - 1]),那么第二次遍历时,fish[i] 的值只可能增加,不会减小,因此 fish[i] > fish[i - 1] 仍然成立。
  • 如果 fish[i] 在第一次遍历中不比 fish[i - 1],第二次遍历时对 fish[i] 的增加也不会影响 fish[i - 1],因为我们接下来就会对fish[i-1]进行判断和修正。

Code

 #include <iostream>
 #include <vector>
 
 int solution(int n, std::vector<int> catsLevels) {
     // Please write your code here
     int len = catsLevels.size();
     std::vector<int> fish(len, 1);
     for (int i = 1; i < len; i++) 
         if (catsLevels[i] > catsLevels[i-1]) fish[i] = fish[i-1] + 1;
     for (int i = len-2; i >= 0; i--) 
         if (catsLevels[i] > catsLevels[i+1] && fish[i] <= fish[i+1]) fish[i] = fish[i+1] + 1;
     int ans = 0;
     for (int i = 0; i < len; i++) ans += fish[i];
     return ans;
 }
 
 int main() {
     std::vector<int> catsLevels1 = {1, 2, 2};
     std::vector<int> catsLevels2 = {6, 5, 4, 3, 2, 16};
     std::vector<int> catsLevels3 = {1, 2, 2, 3, 3, 20, 1, 2, 3, 3, 2, 1, 5, 6, 6, 5, 5, 7, 7, 4};
     std::cout << (solution(3, catsLevels1) == 4) << std::endl;
     std::cout << (solution(6, catsLevels2) == 17) << std::endl;
     std::cout << (solution(20, catsLevels3) == 35) << std::endl;
     return 0;
 }

时间复杂度分析

  • 空间复杂度:代码使用了一个大小为 lenfish 数组来存储每只猫所需的鱼干数量,len 是输入 catsLevels 的大小。因此,空间复杂度为 O(N)
  • 时间复杂度:两次遍历计算fish,以及最后一次遍历fish计算总和,时间复杂度为O(N)