思路
状态转移过程
设 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;
}