Leetcode题库1823. 找出游戏的获胜者(约瑟夫环 C实现)

思路

状态转移过程

设 n 名小伙伴做游戏,计数为k

有n名小伙伴时,第一个离开的小伙伴编号为k,剩下n-1名小伙伴
此时从k+1开始重新计数,若n-1名小伙伴里获胜者编号为p1
那么n名小伙伴里,p1的编号应该是p = k + p1

n-1名小伙伴时,第一个离开的小伙伴编号为k+1+(k-1)=2k,剩下n-2名小伙伴
此时从2k+1开始重新计数,若n-2名小伙伴里获胜者编号为p2
那么n-1名小伙伴里,p2的编号应该是p1 = p2 + k
n名小伙伴里,p2的编号应该是p = (p2 + k) + k
……

状态转移方程

设 n 名小伙伴做游戏,计数为k时,获胜者编号为f(n,k)
由上面推导可知,f(n,k) 与f(n-1,k)的关系如下
f(n,k) = f(n-1,k) + k
因为编号大小不可能超过n,于是有如下修正
f(n,k) = (f(n-1,k) + k)%n

递归思路

模拟上述状态转移方程即可

迭代思路

利用上述状态转移方程
从1名小伙伴的情况 f(1,k),计算2名小伙伴的情况 f(2,k),直至推导到n名小伙伴 f(n,k)

补充

这里给出我几年前第一次遇到约瑟夫环时的题解 链接

代码

递归

参考代码

int findTheWinner(int n, int k){
    if(n == 1) return 1;
        int ans = findTheWinner(n - 1, k) + k;
        return ans % n == 0? n: (ans % n);
}

迭代

参考代码

int findTheWinner(int n, int k){
    int winner = 1;
    for (int i = 2; i <= n; i++) {
        winner = (k + winner - 1) % i + 1;
    }
    return winner;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值