题目描述
在猫星球上,小R负责给排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:
- 每只猫至少得到一斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。
小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干。
解题思路
-
初始化:首先,我们为每只猫分配一斤鱼干,因为规则规定每只猫至少得到一斤鱼干。
-
从左到右遍历:然后,我们从左到右遍历猫的等级列表。如果当前猫的等级高于前一只猫,我们就需要增加当前猫的鱼干数量,确保它比前一只猫多。我们将其鱼干数量设为前一只猫的数量加1。
-
从右到左遍历:接下来,我们从右到左遍历猫的等级列表。这是为了确保如果一个猫的等级高于它右边的猫,它得到的鱼干数量也符合规则。在这个步骤中,如果当前猫的等级高于后一只猫,我们就需要再次检查当前猫的鱼干数量是否足够多(即是否比后一只猫多1)。如果不是,我们就更新当前猫的鱼干数量。
-
计算总鱼干数量:最后,我们计算所有猫得到的鱼干总数,这就是小R至少需要准备的鱼干数量。
代码详解
以下是Java代码实现:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int n, List<Integer> cats_levels) {
// 初始化鱼干分配数组,每只猫至少得到一斤鱼干
List<Integer> fish_distribution = new ArrayList<>();
for (int i = 0; i < n; i++) {
fish_distribution.add(1);
}
// 从左到右遍历,确保等级高的猫得到更多的鱼干
for (int i = 1; i < n; i++) {
if (cats_levels.get(i) > cats_levels.get(i - 1)) {
fish_distribution.set(i, fish_distribution.get(i - 1) + 1);
}
}
// 从右到左遍历,确保等级高的猫得到更多的鱼干
for (int i = n - 2; i >= 0; i--) {
if (cats_levels.get(i) > cats_levels.get(i + 1)) {
fish_distribution.set(i, Math.max(fish_distribution.get(i), fish_distribution.get(i + 1) + 1));
}
}
// 计算总鱼干数量
int total_fish = 0;
for (int fish : fish_distribution) {
total_fish += fish;
}
return total_fish;
}
public static void main(String[] args) {
List<Integer> catsLevels1 = new ArrayList<>();
catsLevels1.add(1);
catsLevels1.add(2);
catsLevels1.add(2);
List<Integer> catsLevels2 = new ArrayList<>();
catsLevels2.add(6);
catsLevels2.add(5);
catsLevels2.add(4);
catsLevels2.add(3);
catsLevels2.add(2);
catsLevels2.add(16);
List<Integer> catsLevels3 = new ArrayList<>();
catsLevels3.add(1);
catsLevels3.add(2);
catsLevels3.add(2);
catsLevels3.add(3);
catsLevels3.add(3);
catsLevels3.add(20);
catsLevels3.add(1);
catsLevels3.add(2);
catsLevels3.add(3);
catsLevels3.add(3);
catsLevels3.add(2);
catsLevels3.add(1);
catsLevels3.add(5);
catsLevels3.add(6);
catsLevels3.add(6);
catsLevels3.add(5);
catsLevels3.add(5);
catsLevels3.add(7);
catsLevels3.add(7);
catsLevels3.add(4);
System.out.println(solution(3, catsLevels1) == 4); // 输出: true
System.out.println(solution(6, catsLevels2) == 17); // 输出: true
System.out.println(solution(20, catsLevels3) == 35); // 输出: true
}
}
思路详解:
在面对猫鱼干分配的问题时,我们需要确保每只猫至少获得一斤鱼干,并且等级高的猫要比等级低的猫获得更多的鱼干。为了有效地解决这个问题,我们可以采用贪心算法。
首先,我们初始化一个数组fish_distribution,用于记录每只猫应得的鱼干数量。根据题目要求,每只猫至少获得一斤鱼干,所以我们首先将数组中的所有元素初始化为1。
接下来,我们进行从左到右的遍历。在遍历过程中,我们比较当前猫的等级与前一只猫的等级。如果当前猫的等级高于前一只猫,那么为了确保等级高的猫获得更多的鱼干,我们将当前猫的鱼干数量设置为前一只猫的数量加1。这样,从左到右遍历一遍后,我们就能确保所有等级高于其左边邻居的猫都获得了更多的鱼干。
然而,仅仅从左到右遍历还不够,因为可能存在一个猫的等级既高于其左边的猫又高于其右边的猫的情况。为了确保这种情况下的猫也能获得更多的鱼干,我们需要进行从右到左的遍历。在遍历过程中,我们再次比较当前猫的等级与其右边邻居的等级。如果当前猫的等级更高,我们再次检查当前猫的鱼干数量是否足够多(即是否比其右边邻居的猫多1)。如果不是,我们就更新当前猫的鱼干数量,确保它满足等级差异的要求。
最后,我们计算所有猫获得的鱼干总数。通过遍历fish_distribution数组,我们将每只猫获得的鱼干数量相加,得到总数量。这个总数量就是小R至少需要准备的鱼干数量。
综上所述,我们采用贪心算法,通过两次遍历猫的等级列表,确保了等级高的猫能够获得更多的鱼干,并且满足了题目的所有要求。这个算法的时间复杂度是O(n),因为我们只遍历了猫列表两次,空间复杂度也是O(n),因为我们使用了额外的数组来存储每只猫的鱼干数量。这种算法既高效又简洁,非常适合解决这类问题。
总结
- 初始化:每只猫至少分配一斤鱼干。
- 从左到右遍历:确保等级高的猫比左边的猫得到更多的鱼干。
- 从右到左遍历:确保等级高的猫比右边的猫得到更多的鱼干。
- 计算总鱼干数量:累加每只猫得到的鱼干数量,得到总数量。
这个算法的时间复杂度是O(n),因为我们只遍历了猫列表两次,空间复杂度是O(n),因为我们使用了额外的数组来存储每只猫的鱼干数量。