共有 n 名小伙伴一起做游戏。小伙伴们围成一圈,按 顺时针顺序 从 1 到 n 编号。确切地说,从第 i 名小伙伴顺时针移动一位会到达第 (i+1) 名小伙伴的位置,其中 1 <= i < n ,从第 n 名小伙伴顺时针移动一位会回到第 1 名小伙伴的位置。
游戏遵循如下规则:
从第 1 名小伙伴所在位置 开始 。
沿着顺时针方向数 k 名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。
你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤 2 继续执行。
否则,圈子中最后一名小伙伴赢得游戏。
给你参与游戏的小伙伴总数 n ,和一个整数 k ,返回游戏的获胜者。
示例 1:
输入:n = 5, k = 2
输出:3
示例 2 :
输入:n = 6, k = 5
输出:1
解释:小伙伴离开圈子的顺序:5、4、6、2、3 。小伙伴 1 是游戏的获胜者。
提示:
- 1 <= k <= n <= 500
class Solution {
public int findTheWinner(int n, int k) {
int res = 0;
for(int i = 2; i <= n;i++){
res = (res + k) % i;
}
// 上述代码计算出的是按0 1 2 3 4 的最后结果。由于题目是1 2 3 4 5 因此序号+1
return res + 1;
}
}
/*
思路:你要知道最后的结果是3,带着结果去看问题
第一次,【0, 1, 2, 3, 4】,本轮要踢出2 看3
(下一轮开始从3计数,为了方便读者看出规律,将开始计数的那一位移到开头)
第二次,【3, 4, 0, 1】,本轮要踢出0 看1
第三次,【1, 3, 4】,本轮要踢出4 看1
第四次,【1, 3】 本轮要踢出1 看3
第五次,【3】
最后返回3
我们要使用的数学方法,就是从结果0号位置,反推最开始在哪
你从第二次,向上看第一次
你会发现,原来3在0的位置
现在,3在(0 + 3) % 5
=> +3 回到上次的位置
=> %5 防止数组溢出,并且数组本来就是循环数组
从第三次看第二次:
3 在 1 的位置到3 在 0的位置: (1 + 3) % 4 = 0 3->m 4 ->此时数组长度
f(n) = ( f(n - 1) + m ) % n
解释意思:
f(n) 表示上一次
f(n - 1) 表示这次,因为我们要从这次回推上一次
m 表示隔几个
n表示上一次的数组长度
*/