问题描述
小M正在玩一个数组比赛游戏,游戏规则如下:每回合游戏都在所有元素互不相同的数组 arr 的前两个元素 arr[0] 和 arr[1] 之间进行。较大的整数将会取得这一回合的胜利并保留在位置 0,而较小的整数则会被移至数组的末尾。比赛继续,直到某个整数连续赢得 k 次,这个整数即为比赛的赢家。
给定一个整数数组 arr 和一个整数 k,请你返回赢得比赛的整数。题目数据保证游戏中一定存在赢家。
思路
根据题目的描述,我们知道,比赛输了的元素会排到数组末尾,如果前面一直没有一个人是赢家,那么给定数组中元素值最大的那个元素就是赢家,所以我们从前向后去遍历每个元素,看他是否能够连续赢下 k 次,如果能,该元素就是答案,直接返回;如果不能,则就需要继续遍历
首先考虑 k = 1 时的情况,这种情况下,只有第一个元素和第二个元素有一回合游戏,所以直接比较第一个和第二个元素的大小,更大的元素就是答案,直接返回
当 k > 1时,我们需要不断向后枚举数字,与当前胜利整数比较。因此,需要维护上一回合比赛中取得胜利的整数和该整数取得连续胜利的回合数。
-
如果 prev > curr,则 prev 不变,累加计数器,等于 k 时说明连续赢得 k 次,返回
-
如果 prev < curr,则更新胜者,重置计数器
同时在这个过程中维护数组的最大值
如果遍历整个数组都没有找到赢家,那么数组最大值就是答案
解题方法
设置 prev 表示胜者,计数器 consecutive 记录胜利次数
当 k = 1 时,只进行一次比赛,所以答案就是 arr[0] 和 arr[1] 中的胜者
之后枚举数组中每个数,与胜者比较,如果胜利,就更新胜者,重置胜利次数计数器 consecutive;如果失败,胜者不变,胜场次数 + 1
在这个过程中,每次都顺带更新数组的最大值 maxNum
在遍历过程中,如果发现计数器达到 k 次,那么当前 prev 就是连续赢得 k 次的第一个元素,返回 prev
如果遍历完整个数组都没有找到,那么一定是数组最大值连续赢得 k 次,返回 maxNum
复杂度
时间复杂度:
O(N)
对于给定的数组,枚举每一个元素,每个元素最多遍历一次
空间复杂度:
O(1)
仅使用个别变量维护更新 O(1)
代码
public class Main { public static int solution(int[] arr, int k) { int prev = Math.max(arr[0], arr[1]); if (k == 1) { return prev; } int consecutive = 1; int maxNum = prev; int length = arr.length; for (int i = 2; i < length; i++) { int curr = arr[i]; if (prev > curr) { consecutive++; if (consecutive == k) { return prev; } } else { prev = curr; consecutive = 1; } maxNum = Math.max(maxNum, curr); } return maxNum; } 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); }}