问题描述
有
n
位玩家在进行比赛,玩家编号依次为0
到n - 1
。给你一个长度为
n
的整数数组skills
和一个 正 整数k
,其中skills[i]
是第i
位玩家的技能等级。skills
中所有整数 互不相同 。所有玩家从编号
0
到n - 1
排成一列。比赛进行方式如下:
- 队列中最前面两名玩家进行一场比赛,技能等级 更高 的玩家胜出。
- 比赛后,获胜者保持在队列的开头,而失败者排到队列的末尾。
这个比赛的赢家是 第一位连续 赢下
k
场比赛的玩家。请你返回这个比赛的赢家编号。
示例
示例 1:
**输入:**skills = [4,2,6,3,9], k = 2
**输出:**2
解释:
一开始,队列里的玩家为
[0,1,2,3,4]
。比赛过程如下:
- 玩家 0 和 1 进行一场比赛,玩家 0 的技能等级高于玩家 1 ,玩家 0 胜出,队列变为
[0,2,3,4,1]
。- 玩家 0 和 2 进行一场比赛,玩家 2 的技能等级高于玩家 0 ,玩家 2 胜出,队列变为
[2,3,4,1,0]
。- 玩家 2 和 3 进行一场比赛,玩家 2 的技能等级高于玩家 3 ,玩家 2 胜出,队列变为
[2,4,1,0,3]
。玩家 2 连续赢了
k = 2
场比赛,所以赢家是玩家 2 。示例 2:
**输入:**skills = [2,5,4], k = 3
**输出:**1
解释:
一开始,队列里的玩家为
[0,1,2]
。比赛过程如下:
- 玩家 0 和 1 进行一场比赛,玩家 1 的技能等级高于玩家 0 ,玩家 1 胜出,队列变为
[1,2,0]
。- 玩家 1 和 2 进行一场比赛,玩家 1 的技能等级高于玩家 2 ,玩家 1 胜出,队列变为
[1,0,2]
。- 玩家 1 和 0 进行一场比赛,玩家 1 的技能等级高于玩家 0 ,玩家 1 胜出,队列变为
[1,2,0]
。玩家 1 连续赢了
k = 3
场比赛,所以赢家是玩家 1 。提示:
n == skills.length
2 <= n <= 10^5
1 <= k <= 10^9
1 <= skills[i] <= 10^6
skills
中的整数互不相同。
问题分析:
周赛的第二题,我现在的实力也就做做第一第二题。。。这道题和1535. 找出数组游戏的赢家 - 力扣(LeetCode)题是一模一样的,就是返回值略有不同。我的解法是纯纯的模拟,用一个双端队列来模拟这个比赛全流程。每次取出队首两个元素进行比较,胜者继续留在队首,败者去队尾,一直到决出胜者。这里要注意,由于k可能非常大,所以我们要进行剪枝,去除不必要的循环,主要就是当一个人,他获胜的次数已经超过了数组元素的个数,那无论再怎么循环下去,都是他会成为最终胜者。
代码如下:
cpp
class Solution {
public:
int findWinningPlayer(vector<int>& skills, int k) {
// 当k==1时特殊处理,返回0和1之间的胜者下标
if(k == 1){
return skills[0] > skills[1] ? 0 : 1;
}
int n = skills.size();
deque<pair<int, int>> Q;
// 使用pair类型存下标和对应skill
for(int i = 0; i < n; ++i){
Q.push_back({i, skills[i]});
}
int ans = 0;
int res = -1;
while(ans != k){
// 取队首两个元素
pair<int, int> F = Q.front();
Q.pop_front();
pair<int, int> S = Q.front();
Q.pop_front();
// 如果第一个元素大于第二个,++ans。
if(F.second > S.second){
++ans;
Q.push_front(F);
Q.push_back(S);
}
// 如果第二个元素大于第一个,ans重置为1
else{
ans = 1;
Q.push_back(F);
Q.push_front(S);
}
// 满足条件就退出循环,1535就是把F.first改成F.second就行
if(ans > n || ans == k){
res = F.first;
break;
}
}
return res;
}
};