1823.找出游戏的获胜者

题目描述

共有 n 名小伙伴一起做游戏。小伙伴们围成一圈,按 顺时针顺序 从 1 到 n 编号。确切地说,从第 i 名小伙伴顺时针移动一位会到达第 (i+1) 名小伙伴的位置,其中 1 <= i < n ,从第 n 名小伙伴顺时针移动一位会回到第 1 名小伙伴的位置。

游戏遵循如下规则:

从第 1 名小伙伴所在位置 开始 。
沿着顺时针方向数 k 名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。
你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤 2 继续执行。
否则,圈子中最后一名小伙伴赢得游戏。
给你参与游戏的小伙伴总数 n ,和一个整数 k ,返回游戏的获胜者。

 

示例 1:

输入:n = 5, k = 2
输出:3
解释:游戏运行步骤如下:
1) 从小伙伴 1 开始。
2) 顺时针数 2 名小伙伴,也就是小伙伴 1 和 2 。
3) 小伙伴 2 离开圈子。下一次从小伙伴 3 开始。
4) 顺时针数 2 名小伙伴,也就是小伙伴 3 和 4 。
5) 小伙伴 4 离开圈子。下一次从小伙伴 5 开始。
6) 顺时针数 2 名小伙伴,也就是小伙伴 5 和 1 。
7) 小伙伴 1 离开圈子。下一次从小伙伴 3 开始。
8) 顺时针数 2 名小伙伴,也就是小伙伴 3 和 5 。
9) 小伙伴 5 离开圈子。只剩下小伙伴 3 。所以小伙伴 3 是游戏的获胜者。


示例 2:

输入:n = 6, k = 5
输出:1
解释:小伙伴离开圈子的顺序:5、4、6、2、3 。小伙伴 1 是游戏的获胜者。


来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-winner-of-the-circular-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

        看到这题时,我的思路是一种比较笨的方法,就是用一个布尔类型的flag数组,标记每一个人的状态,初始时每个人都为True,当在第一轮游戏中被选中时,将这个人对应位置处的flag标记为False,表示这个人失败了,因为标记为失败之后,就可以在后续的遍历中,通过该标记位知道这个人已经从游戏中退出,可以看作逻辑删除这名玩家,就可以跳过这个人,进而寻找顺时针k个位置的下个失败者,直到游戏只有一个人存在时,start中记录的即为获胜者的编号。

        实现起来,时间复杂度非常的高,达到了O(nk)量级,因为对每一个人,都要进行k步的模拟寻找下一个符合条件的失败者。这种方法不仅时间复杂度高,而且数组的下标很容易出现越界,改了三次才成功通过,最后的用时1800+ms属实是让我蚌埠住了。

        参考题解之后,我发现大可不必如此大费周章的遍历,寻找失败者,只要动态的更新玩家数组就可以了。用一个数组存储1-n名玩家的编号,start=0初始位置,更新时loser=(start+k-1)%len(ans),表示失败者的位置,另外还要更新下一轮游戏起始者的位置start=loser if loser!=len(ans)-1  else 0,就是说如果当前轮求出的失败者不是位于所剩玩家数组的最后一个,就让起始位置为刚才求出的失败者的位置,因为要接下来要删除改位置处的失败者,相当于让失败者后一个人当下轮游戏的开始者,但如果失败者已经是当前数组的最后一人,那么由于求余的性质,肯定是下标为0的人是当前失败者的后一个人,就让下轮游戏的开始者为0即可,做完以上两步更新操作后,就可以放心的把当前求出的本轮游戏失败者从玩家数组中删除了。删除之后动态的维护这个玩家数组,每轮游戏失去一个失败者,直到最后数组中只有一人时,就是要求的答案。

代码实现

1.我的实现思路:模拟依次遍历

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        flag=[True for i in range(n+1)]
        round=1
        start=1
        while round<n:
            i=1
            while i<k :
                if flag[start%n+1]:
                    i+=1
                start=start%n+1
            flag[start]=False
            while flag[start]==False:
                start=start%n+1
            round+=1
        return start

2.参考的思路:直接计算

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        start,ans=0,[i for i in range(1,n+1)]
        while len(ans)>1:
            loser=(start+k-1)%len(ans)
            start=loser if loser!=len(ans)-1 else 0
            del ans[loser]
        return ans[0]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值