约瑟夫环递推详解(圆圈中最后剩下的数字)

在做编程题时遇上约瑟夫环问题:

0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

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

题目来源:力扣(LeetCode)如果看不懂可以百度其它约瑟夫环问题
链接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof

现在我们列个表来举例:假设人总数n=5,每次杀第m=3个人,我们可以列出如下表

01234
12345
4512 
245  
24   
4    

第一行为每个数字的下标位置,从0开始:

现在假设我们已经知道了最后一个留下来的是4号,那么当在倒数第二次杀人的时候我们怎么直接找出4号呢?

即转化位求在倒数第二行查找4号的位置:

我们可以由规则知道,其实每杀一个人,则表中的整行向左移动m=3位,那么由倒数第一行回到倒数第二行4号的位置就应该右移m=3位,则我们可以判断出,此时4号的位置是3+0,如果不进行轮转的话,那么四号的位置就是3,但是此时数组大小只有2,即它所在的位置需要对数组大小进行取余(这个类似hash表的插入方式),那么在倒数二行找到4号位置就是3%2=1了。

同理,在倒数第三行要找到4号:

还得将倒数第二行的位置向右移m=3位才是它在第三行的实际位置,即1+m=4,但是仍然的,此时数组大小为3,我们必须对它进行取余即在倒数三行的位置为4%3=1

依此类推,我们知道任何n的时候,其对应结果的位置都是上一结果n-1的位置右移m位后对n取余

即可以得到公式,f(n,m)=(f(n-1,m)+m)%n;

式子中 f(n,m)表示的是在人数等于n的时候,存活者所在的位置,且易知f(1,m)=0;

一下是c++程序,返回的结果是第几个人,从1开始;与leetcode问题返回结果有所不同,请注意

//返回的是第几个人,从1开始
int Survival(int n, int m)
{
    int sur = 0;
    //从倒数第二行开始算
    for(int i=2; i<=n; i++)
    {
        sur = (sur + m) % i ;//即获得当前人数时,此幸存者的位置
    }
    return sur + 1;//因为是位置,所以下标从0开始,比实际人的标号小1,所以要加回去
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值