问题描述
在猫星球上,小R负责给一行排队的猫分发鱼干。每只猫有一个等级,等级越高的猫应该得到更多的鱼干。规则如下:
- 每只猫至少得到一斤鱼干。
- 如果一只猫的等级高于它相邻的猫,它就应该得到比相邻的猫更多的鱼干。
小R想知道,为了公平地满足所有猫的等级差异,他至少需要准备多少斤鱼干。
思路分析
-
问题本质:
- 需要确保每只猫的鱼干数量满足两个条件:每只猫至少得到一斤鱼干,且如果猫的等级高于相邻的猫,它应该得到更多的鱼干。
- 使用两次遍历的贪心算法来解决这个问题。第一次从左到右遍历,确保每只猫的鱼干数量不小于它左边的猫。第二次从右到左遍历,确保每只猫的鱼干数量不小于它右边的猫。
-
解决方案:
- 初始化鱼干数组:所有猫的初始鱼干数量都设为1。
- 第一次遍历:从左到右遍历,如果当前猫的等级高于左边的猫,更新当前猫的鱼干数量为左边猫的鱼干数量加1。
- 第二次遍历:从右到左遍历,如果当前猫的等级高于右边的猫,更新当前猫的鱼干数量为右边猫的鱼干数量加1,并取两者中的最大值。
- 计算总鱼干数量:遍历鱼干数组,计算所有猫的鱼干总数。
代码详解
import java.util.ArrayList;
import java.util.List;
public class Main {
public static int solution(int n, List<Integer> cats_levels) {
// 初始化鱼干数组,每只猫至少得到一斤鱼干
int[] fish = new int[n];
for (int i = 0; i < n; i++) {
fish[i] = 1;
}
// 从左到右遍历,确保每只猫的鱼干数量正确
for (int i = 1; i < n; i++) {
if (cats_levels.get(i) > cats_levels.get(i - 1)) {
fish[i] = fish[i - 1] + 1;
}
}
// 从右到左遍历,确保每只猫的鱼干数量正确
for (int i = n - 2; i >= 0; i--) {
if (cats_levels.get(i) > cats_levels.get(i + 1)) {
fish[i] = Math.max(fish[i], fish[i + 1] + 1);
}
}
// 计算总鱼干数量
int sum = 0;
for (int i = 0; i < n; i++) {
sum += fish[i];
}
return sum;
}
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);
System.out.println(solution(6, catsLevels2) == 17);
System.out.println(solution(20, catsLevels3) == 35);
}
}
知识总结
-
贪心算法:
- 贪心算法是一种在每个步骤中都选择当前最优解的算法,适用于某些特定的优化问题。
- 在这个问题中,通过两次遍历(从左到右和从右到左)来确保每只猫的鱼干数量满足条件,是一种典型的贪心算法应用。
-
字符频次统计:
- 这个问题没有涉及字符频次统计,但可以通过类似的逻辑来解决问题,即逐步更新每个元素的值,确保满足特定的条件。
-
条件判断:
- 使用
if语句来检查猫的等级是否高于相邻的猫,确保鱼干数量的更新符合规则。 - 通过
Math.max函数来取两个值中的最大值,确保鱼干数量满足从左到右和从右到左的条件。
- 使用
-
代码优化:
- 通过使用数组
fish来记录每只猫的鱼干数量,可以提高代码的执行效率。 - 在
main函数中添加更多的测试用例,确保代码的正确性和鲁棒性。
- 通过使用数组
个人理解与学习建议
-
理解贪心算法:
- 贪心算法是一种非常实用的算法,通过在每个步骤中选择当前最优解,可以高效地解决某些优化问题。
- 通过这个题目,可以加深对贪心算法的理解,学会如何在实际问题中应用。
-
代码可读性:
- 使用有意义的变量名,如
fish、cats_levels等,可以提高代码的可读性。 - 添加注释,解释每一步的逻辑,有助于他人理解代码。
- 使用有意义的变量名,如
-
测试用例:
- 在
main函数中添加更多的测试用例,确保代码的正确性和鲁棒性。 - 测试用例应涵盖各种边界情况和特殊输入,确保代码在所有情况下都能正确运行。
- 在
-
学习建议:
- 多做练习:通过多做类似的题目,可以提高对贪心算法的理解和应用能力。
- 思考边界情况:在编写代码时,思考各种边界情况,确保代码的鲁棒性。
- 代码模块化:将代码分成多个函数或模块,可以提高代码的可维护性和可读性。