编程示例:约瑟夫环问题

编程示例:约瑟夫环问题

1约瑟夫环的故事

在浩瀚的计算机语言中,总有一些算法------虽然码量很少,

但却能完美又巧妙地解决那些复杂的问题。接下来,

我们要介绍的"约瑟夫环"问题就是一个很好的例子。

这个问题来源于犹太人约瑟夫经历过的故事,在罗马人

占领乔塔帕特后,约瑟夫和他的朋友与39 个犹太人躲到

一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,

于是决定了一个自杀方式,41个人排成一个圆圈,由第1

个人开始报数,每报数到第3人时,该人就必须自杀,然

后再由下一个人重新报数,直到所有人都自杀身亡为止。

然而约瑟夫和他的朋友并不想遵从这个规则,于是,

他们想出新的思路:从一个人开始,越过k-2个人(

因为第一个人已经被越过),并杀掉第k个人。接着,再

越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,

直到最终只剩下一个人留下,这个人就可以继续活着。

问题是,给定了和,一开始要站在什么地方才能避免

被处决?如果你是约瑟夫,你会站在什么样的位置呢?

数数与大家一起,从运用以下两个方面来解决这个问题。

在这场逃生游戏中,约瑟夫的办法是:他要和他的朋友先假装

遵从,然后将朋友与自己安排在第16个与第31个位置,于是逃

过了这场死亡游戏。约瑟夫安排的位置和你想的位置一样吗?

看完这个"约瑟夫环"问题,如果你是当时逃生的人之一,

你会选择遵从规则,还是改变规则呢?

2 该问题的解法的历史回顾

有模拟法和数学推导法,其中美国的高纳德教授还在

<<具体数学>>的书中,给出了推导公式

f(N,M)=(f(N-1,M)+M)%N

3 能应用于面试的最佳性能的另类解法

假设初始编号为1,2,······,n,现在考虑一种新的编号方式。

第一个人不会被踢掉,那么他的编号从n开始往后加1,变成n+1,

然后第二个人编号变为n+2,直到第q个人,他被踢掉了。然后

第q+1个人编号继续加1,变成了n+q,依次下去。考虑当前踢到

的人编号为kq,那么此时已经踢掉了k个人,所以接下去的人新

的编号为n+k(q-1)+1......

所以编号为kq+d的人编号变成了n+k(q-1)+d,其中1<=d<q。

直到最后,可以发现活下来的人编号为qn,问题是怎么根据

这个编号推出他原来的编号?以n=10,q=3为例,下图就是每

个人新的编号:

令N=n+k(q-1)+d,那么他上一轮的编号是kq+d=kq+N-n-k(q-1)=k+N-n,

因为k=(N-n-d)/(q-1)=[(N-n-1)/(q-1)],所以上一次编号可以写为

(N-n-1)/(q-1)\]+N-n 如果用D=qn+1-N代替N将会进一步简化算法: ![](https://file.jishuzhan.net/article/1768473373026816002/05f929bf487c01558001c0f29ed0335e.webp) 算法伪代码如下: D=1 while D\<=(q-1)n: D=k Ans=qn+1-D 其中k=Dq/(q-1) ## 4 约瑟夫环问题的C++代码展示 ![](https://file.jishuzhan.net/article/1768473373026816002/12a1f7442c55ef0c943fc8dc18191f46.webp)

相关推荐
xrkhy6 分钟前
Java全栈面试题及答案汇总(3)
java·开发语言·面试
橘颂TA8 分钟前
【Linux】从 “抢资源” 到 “优雅控场”:Linux 互斥锁的原理与 C++ RAII 封装实战(Ⅰ)
linux·运维·服务器·c++·算法
码农水水21 分钟前
阿里Java面试被问:单元测试的最佳实践
java·面试·单元测试
YGGP23 分钟前
【Golang】LeetCode 19. 删除链表的倒数第 N 个节点
算法·leetcode·链表
池塘的蜗牛30 分钟前
mmse-based-OFDM-signal-processing(2)
算法
Kris_LinSD39 分钟前
算法小实验——分治算法快速排序问题实验(含报告)
c语言·算法
Super小白&40 分钟前
十大经典排序算法详解(附C语言实现+复杂度分析)
c语言·算法·排序算法
Eloudy40 分钟前
Birkhoff 多胞形,双随机矩阵的几何世界
算法
2503_946971861 小时前
【SystemDesign/HA】2025年度高可用分布式仿真节点与预测模型容灾演练配置 (Disaster Recovery Config)
大数据·分布式·算法·系统架构·数据集
GrowingYi1 小时前
算法基础技术栈
数据结构·算法