约瑟夫环-圆圈中最后剩下的数字

圆圈中最后剩下的数字
        0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
        例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

        示例  1:
                输入:  n  =  5,  m  =  3
                输出: 3
        示例  2:
                输入:  n  =  10,  m  =  17
                输出: 2
         
        限制:
                1  <=  n <=  10^5
                1  <=  m  <=  10^6

自我解答:
        闹心,又是被虐的一次。。。初看这个题觉得很简单,感觉自己10分钟之内就能写出来。
        用程序模拟很容易实现,但若数比较大,应该会超时,试着写出来了,果然。但实在想不到其他的办法了。

网友解答:
        数学,数学,又是数学。这是一个经典数学问题--  “约瑟夫环”:
        有  N  个人  围成一圈,从第一个人开始报数,每  M  个人便杀掉一人,请问最后留下的是第几个人。
                公式:
                        f(N,  M)  =  (f(N−1,  M)  +  M)  %  N

                ·  f(N,  M)表示,N个人报数,每报到M时杀掉那个人,最终胜利者的编号
                ·  f(N−1,  M)表示,N-1个人报数,每报到M时杀掉那个人,最终胜利者的编号

        公式推导:
                我们用数字表示每一个人:1、2、3、4、5、6、7、8、9、10、11
                11个人,他们先排成一排,假设每报到3的人被杀掉。
                图示:
约瑟夫环.png
                将上面表格的每一行看成数组,这个公式描述的是:幸存者在这一轮的下标位置

                f(1,  3):只有1个人了,那个人就是获胜者,他的下标位置是0
                f(2,  3)  =  (f(1,  3)  +  3)  %  2  =  3  %  2  =  1:在有2个人的时候,胜利者的下标位置为1
                f(3,  3)  =  (f(2,  3)  +  3)  %  3  =  4  %  3  =  1:在有3个人的时候,胜利者的下标位置为1
                f(4,  3)  =  (f(3,  3)  +  3)  %  4  =  4  %  4  =  0:在有4个人的时候,胜利者的下标位置为0
                ……
                f(11  ,  3)  =  6

        算法实现:

def last_remaining(n: int, m: int) -> int:
    left = 0
    for i in range(2, n + 1):
        left = (left + m) % i
    return left


if __name__ == '__main__':
    print(last_remaining(5, 3))

约瑟夫环参考链接:https://blog.csdn.net/u011500062/article/details/72855826
原题链接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof