问题描述
小M正在玩一个数组比赛游戏,游戏规则如下:每回合游戏都在所有元素互不相同的数组 arr 的前两个元素 arr[0] 和 arr[1] 之间进行。较大的整数将会取得这一回合的胜利并保留在位置 0,而较小的整数则会被移至数组的末尾。比赛继续,直到某个整数连续赢得 k 次,这个整数即为比赛的赢家。
给定一个整数数组 arr 和一个整数 k,请你返回赢得比赛的整数。题目数据保证游戏中一定存在赢家。
思路分析
-
问题本质:
- 需要模拟一个比赛过程,直到某个整数连续赢得
k次。 - 由于数组中的元素互不相同,比赛过程中不会出现平局。
- 需要模拟一个比赛过程,直到某个整数连续赢得
-
解决方案:
-
初始化变量:
winner:记录当前的赢家。consecutiveWins:记录当前赢家连续获胜的次数。
-
特殊情况处理:
- 如果
k大于等于数组的长度减1(即k >= n - 1),那么比赛的赢家一定是数组中的最大值,因为最大值在前n-1回合中会连续获胜。
- 如果
-
模拟比赛:
-
从左到右遍历数组,模拟每回合的比赛:
- 如果
arr[i]大于winner,更新winner为arr[i],重置consecutiveWins为1。 - 否则,
consecutiveWins增加1。
- 如果
-
如果
consecutiveWins达到k,返回winner。
-
-
代码详解
import java.util.Arrays;
public class Main {
public static int solution(int[] arr, int k) {
int n = arr.length;
int winner = arr[0];
int consecutiveWins = 0;
// 如果 k 大于等于数组长度减1,直接返回数组中的最大值
if (k >= n - 1) {
int max = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 模拟比赛过程
for (int i = 1; i < n; i++) {
if (arr[i] > winner) {
winner = arr[i];
consecutiveWins = 1;
} else {
consecutiveWins++;
}
// 如果某个整数连续赢得 k 次,返回该整数
if (consecutiveWins == k) {
return winner;
}
}
return winner;
}
public static void main(String[] args) {
int[] arr1 = {2, 1, 3, 5, 4, 6, 7, 9};
System.out.println(solution(arr1, 2) == 5);
int[] arr2 = {3, 2, 1, 4};
System.out.println(solution(arr2, 10) == 4);
int[] arr3 = {1, 9, 8, 7, 6, 5, 4, 3, 2, 11};
System.out.println(solution(arr3, 7) == 9);
}
}
知识总结
-
贪心算法:
- 贪心算法是一种在每个步骤中都选择当前最优解的算法,适用于某些特定的优化问题。
- 在这个问题中,通过逐步更新赢家和连胜次数,可以高效地找到最终的赢家。
-
条件判断:
- 使用
if语句来判断当前元素是否大于赢家,以及连胜次数是否达到k。 - 通过
Math.max函数来更新最大值,确保特殊情况处理的正确性。
- 使用
-
数组操作:
- 使用数组的索引来访问和更新元素。
- 通过
for循环遍历数组,模拟比赛过程。
-
代码优化:
- 通过处理特殊情况(
k >= n - 1),可以提前返回结果,提高代码的效率。 - 在
main函数中添加更多的测试用例,确保代码的正确性和鲁棒性。
- 通过处理特殊情况(
个人理解与学习建议
-
理解贪心算法:
- 贪心算法在每一步中选择当前最优解,最终达到全局最优解。通过这个题目,可以加深对贪心算法的理解和应用。
-
代码可读性:
- 使用有意义的变量名,如
winner、consecutiveWins等,可以提高代码的可读性。 - 添加注释,解释每一步的逻辑,有助于他人理解代码。
- 使用有意义的变量名,如
-
测试用例:
- 在
main函数中添加更多的测试用例,确保代码的正确性和鲁棒性。 - 测试用例应涵盖各种边界情况和特殊输入,确保代码在所有情况下都能正确运行。
- 在
-
学习建议:
- 多做练习:通过多做类似的题目,可以提高对贪心算法的理解和应用能力。
- 思考边界情况:在编写代码时,思考各种边界情况,确保代码的鲁棒性。
- 代码模块化:将代码分成多个函数或模块,可以提高代码的可维护性和可读性。