500 比赛的赢家
问题描述
小M正在玩一个数组比赛游戏,游戏规则如下:每回合游戏都在所有元素互不相同的数组 arr 的前两个元素 arr[0] 和 arr[1] 之间进行。较大的整数将会取得这一回合的胜利并保留在位置 0,而较小的整数则会被移至数组的末尾。比赛继续,直到某个整数连续赢得 k 次,这个整数即为比赛的赢家。
给定一个整数数组 arr 和一个整数 k,请你返回赢得比赛的整数。题目数据保证游戏中一定存在赢家。
测试样例
输入:arr = [2, 1, 3, 5, 4, 6, 7, 9],k = 2
输出:5
第一次比赛的结果 [2, 3, 5, 4, 6, 7, 9, 1], 2 赢了 1 次。
第二次比赛的结果 [3, 5, 4, 6, 7, 9, 1, 2], 2 赢了 1 次, 3 赢了 1 次。
第三次比赛的结果 [5, 4, 6, 7, 9, 1, 2, 3], 2 赢了 1 次, 3 赢了 1 次, 5 赢了 1 次。
第四次比赛的结果 [5, 6, 7, 9, 1, 2, 3, 4], 2 赢了 1 次, 3 赢了 1 次, 5 赢了 2 次。
因此 5 就是最早的连续赢得2次的整数,正确答案为5。
解题思路
一个显而易见的思路就是模拟比赛的过程,和上述测试样例描述的一样,每次将输掉的数字移动到数组的末尾并统计连续赢的次数。但这样会带来一个问题,如果k是一个很大的数字,重复的对数组进行扩充操作会带来时间上和空间上的开销。
实际上我们并不需要对数组扩充,也就是说我们并不需要考虑输掉的数字移动到数组末尾后具体的顺序。因为对于一个所有元素不同的数组,数组中最大的数一定会连续打赢数组内其他所有的数字。也就是说如果走到arr的末尾还没找到连续赢得k次的数字,那么arr数组中最大的数字就是答案。如输入:arr = [3, 2, 1, 4],k = 10,无论前面的3,2,1是以何种输赢顺序移动到末尾的,4总是能将他们击败。
因此我们只需要考虑在arr的n个数字中进行比赛,如果能找到一个数字连续赢得k次比赛,那么该数字就是答案。如果找不到这样的数,arr中最大的数就是答案。
代码
def solution(arr: list, k: int) -> int:
## 初始化最大值mx和赢的次数win
mx = arr[0]
win = 0
#从下标1开始遍历
for i in arr[1:]:
if i > mx:
#当前数字大于mx,重置win以及更新mx
win = 1
mx = i
else:
#当前数字小于mx,增加mx赢的次数
win+=1
if win == k :
#当赢得次数满足k返回结果
return mx
#遍历完数字还没赢k次返回最大值
return mx
复杂度分析
mx 和 win 两个变量为额外的空间开销,空间复杂度为O(1)。
时间上只遍历了一次arr数组,时间复杂度为O(1)。