题目描述
给你一个由 不同 整数组成的整数数组 arr
和一个整数 k
。
每回合游戏都在数组的前两个元素(即 arr[0]
和 arr[1]
)之间进行。比较 arr[0]
与 arr[1]
的大小,较大的整数将会取得这一回合的胜利并保留在位置 0
,较小的整数移至数组的末尾。当一个整数赢得 k
个连续回合时,游戏结束,该整数就是比赛的 赢家。
返回赢得比赛的整数。
题目数据 保证 游戏存在赢家。
样例
输入:arr = [2,1,3,5,4,6,7], k = 2
输出:5
解释:一起看一下本场游戏每回合的情况:
回合 | 数组 | 获胜整数 | 连胜回合数
1 | [2,1,3,5,4,6,7] | 2 | 1
2 | [2,3,5,4,6,7,1] | 3 | 1
3 | [3,5,4,6,7,1,2] | 5 | 1
4 | [5,4,6,7,1,2,3] | 5 | 2
因此将进行 4 回合比赛,其中 5 是赢家,因为它连胜 2 回合。
输入:arr = [3,2,1], k = 10
输出:3
解释:3 将会在前 10 个回合中连续获胜。
输入:arr = [1,9,8,2,3,7,6,4,5], k = 7
输出:9
输入:arr = [1,11,22,33,44,55,66,77,88,99], k = 1000000000
输出:99
限制
2 <= arr.length <= 10^5
1 <= arr[i] <= 10^6
arr
所含的整数 各不相同。1 <= k <= 10^9
算法
(模拟) $O(n)$
- 我们仅遍历每个整数一次,如果每个整数都被遍历一次后,没有整数连胜次数达到
k
,则最终答案一定是数组最大的整数(也就是最后一次比较中获胜的整数)。 - 在模拟游戏时,我们不必真正移动数字,只需要用两个下标表示即将要比较的两个整数。
时间复杂度
- 每个数字最多遍历一次,故总时间复杂度为 $O(n)$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码1
#define max(x, y) ((x) > (y) ? (x) : (y))
class Solution {
public:
int getWinner(vector<int>& arr, int k) {
const int n = arr.size();
int x = 0, y = 1;
bool XLessThanY = arr[x] < arr[y];
int counter = 0;
while (max(x, y) < n && counter < k) {
if (arr[x] > arr[y]) {
if (XLessThanY) {
XLessThanY = false;
counter = 0;
}
counter++;
y = max(x, y) + 1;
} else {
if (!XLessThanY) {
XLessThanY = true;
counter = 0;
}
counter++;
x = max(x, y) + 1;
}
}
if (XLessThanY) return arr[y];
return arr[x];
}
};
C++ 代码2
- 我们可以在遍历过程中比较相邻的两个数字。
- 如果出现前者大于后者,则增加连胜次数,然后交换。否则连胜次数置为 1。
class Solution {
public:
int getWinner(vector<int>& arr, int k) {
const int n = arr.size();
int cnt = 0;
for (int i = 0; i < n - 1; i++) {
if (cnt >= k)
return arr[i];
if (arr[i] > arr[i + 1]) {
arr[i + 1] = arr[i];
cnt++;
} else {
cnt = 1;
}
}
return arr[n - 1];
}
};