约瑟夫环问题的数学解 下午和朋友聊天的时候,有朋友提到了约瑟夫环问题 。你和另外 n-1 个人围成一个圈,按 1,2,...,n 依次编号 。第一个人从 1 开始报数,数到 k 的人会被杀掉,然后下一个人重新从 1 开始报数 。如此往复,直到最后只剩下一个人 。问题是,你应该如何选择自己的初始位置,才能保证最后不被杀掉呢?
速度越快的算法当然越好,毕竟这是一个生死攸关的问题 。下面你将会看到,我们如何通过一些基本的数学推导最终得到这个问题的递推解 。
考虑这样一种相对简单的情况:总共有 5 个人,数到 3 的人被杀掉 。那么,死亡过程如下图所示:
经过一番模拟之后,我们已经对约瑟夫环问题有了一个大概的直观理解 。下面,尝试使用数学语言来描述这个问题 。
哦对了,假如圆圈里只有你自己,那么你肯定就是最后的幸存者,这是一个极其有用的特殊情况 。
这些是我们的 已知条件 :
这个是我们的 未知数 :
现在考虑一种泛化情形:总共有 n 个人,数到 k 的人被杀掉,其中 n = k 。幸存者的位置为 p n。
显而易见,初始位置为 k 的人将会第一个被杀掉 。此时,经过重新排序之后,问题变成了 n-1 个人的情形 。幸存者的位置为 p n-1。如果能够找到从 p n-1到 p n的递推关系,那么问题就解决了 。
重新排序之后,每个人的位置发生了下面这些变化:
很容易我们能得到这样一个关系式:p n= (p n-1+ k) % n。再加上刚才讨论的特例,只有一个人的情况时,p 1= 1。递推式就已经很明显了 。
当然上文只讨论了 n=k 的情形,实际上对于 nk 的情形,刚才所得到的递推式依然适用,我们就不展开讨论了 。
既然递推式这么简洁明确,那么编码实现就不用写了吧?
文章插图
约瑟夫环(单循环链表)m个人围成一个圈,指定一个数字n,从第一个人开始报数,每轮报到n的选手出局,由下一个人接着从头开始报,最后一个人是赢家 。其中m1,n2 。
用一个不带头节点的循环链表来处理,先构成一个有m个节点的单循环链表,然后由n节点开始计数,每计数到n时对应节点从链表中删除,然后再从删除节点的下一个节点又从1开始计数,直到最后一个节点从链表中删除算法结束 。
1.创建一个空指针first,这个first暂时不动,只指向第一个加入进来的对象 。
2.先创建第一个节点,并用first指向它,同时它的next是它自己,形成一个闭环 。同时创建一个currentNode节点指向最后一个节点,为增加其它节点做准备 。
3.加入其它节点时,首先将currentNode的next设置为新的节点node,然后把新节点的next指向回没有动的first节点形成闭环,最后将currentNode指向新的节点 。
建立一个重要的指针helper,辅助弹出功能
first 当前计数的节点,helper则指向first的上一个节点
first和helper指针同时前移的时候,first数到对应的数字n,helper还是到它的前一个 。弹出first后,first前移以为,helper的next指向first,就弹出了对应的那个节点
约瑟夫环的算法原理约瑟夫环运作如下:
1、一群人围在一起坐成 环状(如:N)
2、从某个编号开始报数(如:K)
3、数到某个数(如:M)的时候,此人出列,下一个人重新报数
【约瑟夫环python 约瑟夫环】4、一直循环,直到所有人出列 ,约瑟夫环结束
秒懂生活扩展阅读
- 怎么找回手机删除的照片免费
- 冰箱冬季用12345哪个档
- 赛龙舟适合的地理环境
- 家装用环氧树脂有毒吗 环氧树脂地坪的优缺点有哪些
- 小米手环2支持第三方软件接入吗
- 广西河池环江发现一组珊瑚化石,或距今300-4亿年
- 三层循环的时间复杂度计算
- 室内环保漆选购技巧是什么
- 环球影城|来到洛杉矶玩什么?环球影城精彩万分,莫妮卡海滩浪漫又唯美
- 金华山兰花怎么养了