问题:0,1,…,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求这个圆圈里剩下的最后一个数字。
注意到,一开始有 n 个人,报到 m 的人出局后,如果我们从刚才出局的那人的下一位开始重新从 1 开始编号,原问题就转化为了一个 n–1 人的问题。如下表所示:
原始编号(i) | 第一个人出局后的编号(j) |
---|---|
m | 0 |
m+1 | 1 |
m+2 | 2 |
… | … |
m-2 | n-2 (n为出局前的总人数) |
m-1 | OUT |
可以看出老编号i和新编号j的关系为:i = (j+m) % n
,于是总结递推公式:
f(n) = (f(n-1) + m) % n
(n > 1),其中f(n)为当场上还有n个人时在场的人的编号。
当最后只剩下一个人的时候,这个人的编号只能是0,即f(1)=0
,现在根据上面的公式反推,推导出当n个人在场时这个最后幸存者的编号。例如:f(2)=(f(1)+m) % 2
,所以range
范围从2开始,执行n-1
次,也就是range(2, n+1)
1 | def LastRemaining_Solution(self, n, m): |