题目思路分析:56贪心猫的鱼干大分配 | 豆包MarsCode AI 刷题

89 阅读4分钟

主要考察算法:贪心算法

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

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

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

思路分析: 1、暴力解法:我们可以将创建一个数组,初始化每一只猫的基础鱼干数值均为1,然后开始遍历整个数组,每个位置判断其与左右位置的大小进行比较以此来判断每一只猫需要获得多少的鱼干。虽然说起来很简单,但是实际操作是很复杂的。为什么呢?我给大家举个例子就知道了,我有一个数组{1, 3, 2, 1},通过我上述的操作每个位置会变成{1, 2, 2, 1},我们会发现,3比2大,但是3和2分发到的鱼干确是一样多的,我们需要再次对数组进行遍历以及操作才能得到{1,3,2,1}这个正确的数组。所以说是暴力,但是其实并不是非常好实现。

那么,有没有什么更加简单的方法的呢? 在介绍之前,先给大家介绍一下什么叫贪心算法。贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。贪心算法在有最优子结构的问题中尤为有效,最优子结构的意思是局部最优解能决定全局最优解。

2、我们以例子{1,2,2,1},我们先对其从左往右遍历(判断a[i]与a[i-1]),可以得到鱼干数组sum = {1, 2, 1, 1}然后我们在从右往左遍历(判断a[i]和a[i + 1]),得到{1,1,2,1}将两个数组合并起来,最终我们可以得到{1,2,2,1}这个正确的序列。我们发现,可以将暴力解法的判断两边给拆分开来,每次先从左往右运用贪心算法,在从右向左运用贪心算法,将得出的每个进行比较取每个位置的最大值。我们就可以得出结果。

具体代码如下(仅供参考):

#include<bits/stdc++.h>
using namespace std;

int solution(int n, std::vector<int> cats_levels) {
  // Please write your code here

  vector<int> sum(n, 1);
  for(int i = 1; i < n; i++)
  {
    if(cats_levels[i] > cats_levels[i - 1])
      sum[i] = sum[i - 1] + 1;
  }
  for(int i = n - 2; i >= 0; i--)
  {
    if(cats_levels[i] > cats_levels[i + 1])
      sum[i] = max(sum[i], sum[i + 1] + 1);
  }
  int total = 0;
  for(int i = 0; i < n; i++)
  {
    total += sum[i];
  }
  return total;
}

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;
}

总结:这个问题再次体现了贪心算法的巧妙之处。从解决过程来看,贪心算法并不是盲目地追求全局最优,而是在每一步都根据当前的局部情况做出看似最优的决策。在这个该问题中,我们每次只考虑相邻猫的等级关系,这是一种局部的视角,但通过两次遍历(正向和反向),这种局部最优的积累最终形成了全局的最优解。这让我认识到贪心算法的关键在于找到合适的局部最优策略,并且要确保这种策略能够逐步导向全局最优。最后,给大家推荐一道类似的例题,就是leetcode上的135题 分糖果,总体思路与本题类似。 感谢大家的观看,若有不足之处请大家不吝赐教。