问题描述
有
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可能非常大,所以我们要进行剪枝,去除不必要的循环,主要就是当一个人,他获胜的次数已经超过了数组元素的个数,那无论再怎么循环下去,都是他会成为最终胜者。
代码如下:
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类型存下标和对应skillfor(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重置为1else{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;}
};