码迷,mamicode.com
首页 > 其他好文 > 详细

递推公式法解决约瑟夫问题

时间:2020-01-03 23:10:53      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:导出   复杂   推导   时间   width   image   表示   http   不难   

约瑟夫问题的描述: n个人围成一圈,第一个人从1开始报数,报m的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的幸存者的编号(编号从零开始)。

 

技术图片

 

如果需要知道每一轮被杀掉的人的编号的话,最好的方法可能是使用链表。不过如果只需要知道最后幸存者的编号的话,链表法的时间复杂度是无法接受的,使用递推公式解决这题会快很多。

 

递推公式百度一下你就知道,但关键是这个递推公式是如何推导出来的呢?

 

我们的目的当然是希望能用m和n表示出最后的幸存者的编号,但不幸的是这很难直接办到。但是用m和n表示出第一个被杀掉的人的编号并不难。那么如何表示呢?请大家先思考一下,忍住不要往下看~

 

↓从此处开始一光年↓

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

如果你的答案是(m - 1) mod n的话,那么你是对的!这个答案应该不难理解。

(注:mod表示取余)

 

技术图片

 

现在我们已经杀掉一个人了,那么就还剩n - 1个人。因为我们是在找递推关系,所以如果能找到n个人的情况与n - 1个人的情况之间的关系的话,递推公式就出来了。而现在刚好圆圈里剩下n - 1个人,就意味着我们接下来需要重点分析这剩下的n - 1个人。

 

根据第一个被杀掉的人的编号,我们可以用m和n表示出其他人的编号,如下图。

技术图片

 

接下来让我们对每个人重新编号。我们把第二轮报数中第一个报数的人,也就是第一个被杀死的人后面的那个人,重新编号为0,后面的人依次为1,2,3....。

 

技术图片

 

哈哈。接下来仔细一看,问题不就已经被转换成了: n - 1个人围成一圈,第一个人从1开始报数,报m的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的幸存者的编号(编号从零开始)。除了“n个人”变成了“n - 1个人"以外,其他条件完全没变。

 

另外,我们也不难观察出新编号和旧编号之间的关系。容易观察出,如果一个人的新编号是i的话,那么他的旧编号就是(m + i) mod n。

 

到了现在,我们已经可以很轻松地推导出递推公式了。我们定义这样一个函数f(x,y) : f(x,y)表示当约瑟夫问题中的n = x,m = y时幸存者的编号。回到上面n - 1个人的情况,显然,幸存者的新编号就是f(n - 1,m),那么根据我们刚刚发现的新编号与旧编号之间的关系,就可以得出幸存者的旧编号是(m + f(n - 1,m)) mod n,这个不正好就是我们所寻找的递推关系嘛?

 

就讲到这里吧。至于具体如何用这个递推公式解决约瑟夫问题,太简单了,就留给你们自己想a.a

递推公式法解决约瑟夫问题

标签:导出   复杂   推导   时间   width   image   表示   http   不难   

原文地址:https://www.cnblogs.com/ZhouYiJoe/p/12147052.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!