约瑟夫问题详解

1.什么是约瑟夫问题

设有编号为1,2,……,n的n(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,再从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,直到所有人全部出圈为止。当任意给定n和m后,设计算法求n个人出圈的次序。

2.暴力解法

最直接的方法就是模拟报数的过程。模拟n-1次报数的过程,每次报数报m个人,第m个人被淘汰。最后查看哪个编号没有报到,该编号为结果。# 学习目标:

但是这样的时间复杂度是O(m*n)。所以当m和n较大的时候,程序的运行时间将特别长。

3.递推公式解法

步骤一:定义f(n)

将n个人报数,报m的人出圈的问题视为f(n,m)问题,并且设该问题的解为f(n)那么n-1个人报数,报m的人出圈的问题视为f(n-1,m)问题,并且设该问题的解为f(n-1)

f(n,m)n个人报数,报m的人出圈
f(n-1,m)n-1个人报数,报m的人出圈
f(1,m)1个人报数,报m的人出圈

步骤二 找到f(n)与f(n-1)之间的关系

假设一开始所有人的序号为:

1 2 3 … n-1 n

那么第一次报数之后,只剩下如下的人:

1 2 3 … m-1 m+1 … n-1 n

并且下一次报数之后,从m+1开始数起,于是序号应该变为:

m+1 m+2 …n-1 n 1 2 3 … m-1
(设这里的序号为x)

将上述序号对应到下列序号:

1 2 3 … n-2 n-1
(设这里的序号为y)

则x和y的关系有:

x=(y+m)%n

其中,这里的序号x代表的是f(n,m)中的序号,序号y代表的是f(n-1,m)中的序号。那么f(n)与f(n-1)的关系有

f(n) =( f(n-1)+m )%n
f(n-1)=( f(n-2)+m )%(n-1)
f(n-2)=( f(n-3)+m )%(n-2)

f(2)=( f(1)+m )%2
f(1)=1

f(1)=1是因为只有一个人,那肯定它就是最后剩下的人,序号为1。

步骤三 根据递推公式写代码

根据递推公式,f(1)=1之后,那么就可以从下往上得到答案。先求得f(2).再求f(3)直到f(n).所以有如下代码。

int yuesefu(int n, int m) {
        int x = 1;
        for (int i = 2; i <= n; i++) {
            x = (x + m) % i;
        }
        return x;
    }
  • 6
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值