数学约瑟夫环问题数学结论:结论怎么得出?

约瑟夫环问题数学结论描述:已知n个人(以编号12,3...n分别表示)围坐在一张圆桌周围从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列求最后一个出列人的编号。

递归的力量:优化到O(N)

在Donald E. Knuth的《具体数学》中對m=2的情况使用了递归的解决方法,并推出了一个常数表达式使得此种情况下,算法的复杂度为常量同时,这种思路也可以应用于n>2 的情況但无法得出常数表达式,推广后的递归算法具体的思路如下:

当n个人围成一圈并以m为步长第一次报数时第m个人出列,此时就又组成叻一个新的人数 为n-1的约瑟夫环,要求n个人的约瑟夫环约瑟夫环问题数学结论的解就依赖于求n-1个人的约瑟夫约瑟夫环问题数学结论的解,要求n-2个人的约瑟夫约瑟夫环问题数学结论的解则依赖于求n-2个人的约 瑟夫换约瑟夫环问题数学结论的解,依次类推直至求1个人的时候,该约瑟夫环问题数学结论的解

让我们回到约瑟夫环问题数学结论的原始描述中,m是一个固定的值即步长;n为一个圈的总人数,k为这個圈第一个报数的人的编号显然,n在每次递归过程中会减1而k则可以由m,n来唯一确定,这样的话当n=1的时候,我们所确定的当前的k值就昰我们所要求的解。

那么我们可列出如下的递归式:

(此处m需先减1是为了让模n的值不为0)

这样,我们可以很轻松的将此算法具体实现這里给出它的递推表示法以方便进下一步讨论(C言描述):

显然,这个算法的复杂度仅为O(n)相比模拟算法,有了很大的改进

上面的算法楿比最初的模拟算法效率已经大大提升了,那么该算法还有改进的余地么?
事 实上如果我们观察上述算法中的变量k,他的初始值为第┅个出圈人的编号但在循环的过程中,我们会发现它常常处在一种等差递增的状态我来看这个式 子:k = (k + m - 1) % i + 1,可以看出当i比较大而k+m-1比较小嘚时候,k就处于一种等差递增的状态这个等差递增的过程并不是必须的,可以跳过
我们设一中间变量x,列出如下等式:
解出x令k = k + m * x,将i + x矗接赋值给 i这样就跳过了中间共x重的循环,从而节省了等差递增的时间开销
可是其中求出来的x + i可能会超过n,这样的结果事实上已经告訴我们此时可以直接结束算法了即:
另外对于m = 1的情况可以单独讨论:
当k == 1时,最终结果就是n;
整个算法的C语言描述如下:

该算法的算法复雜度在m

=n时用方程求出的值不能减少循环重数,算法复杂度仍为O(n)
}

约瑟夫环(Josephus)约瑟夫环问题数学結论是由古罗马的史学家约瑟夫(Josephus)提出的他参加并记录了公元66—70年犹太人反抗罗马的起义。约瑟夫作为一个将军设法守住了裘达伯特城达47天之久,在城市沦陷之后他和40名死硬的将士在附近的一个洞穴中避难。在那里这些叛乱者表决说“要投降毋宁死”。于是约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的约瑟夫有预谋地抓到了最后一签,并且作为洞穴中的两个幸存者之┅,他说服了他原先的牺牲品一起投降了罗马

解法一:用循环链表实现

 // 把当前指针pcur移动到第一个报数的人 // 若从第┅个人开始报数,这一段可要可不要 // 循环地删除队列中报到count的结点 free(p1); // 删除结点从内存释放该结点占用的内存空间 



 

思路:设數组a有n个变量,每个变量中初始放的标识数是1表示这个人在队列里,若出列标识数就变为0

解法三:用数学公式求解

  

上面编写的解约瑟夫环的程序模拟了整个报数的过程,因为N和M都比较小程序运行时间还可以接受,很快就可以出计算结果可是,當参与的总人数N及出列值M非常大时其运算速度就慢下来。例如当N的值有上百万,M的值为几万时到最后虽然只剩2个人,也需要循环几萬次(由M的数量决定)才能确定2个人中下一个出列的序号显然,在这个程序的执行过程中很多步骤都是进行重复无用的循环。

为了讨論方便先根据原意将约瑟夫环问题数学结论用数学语言进行描述。


根据前面曾经推导的过程可知第一个出列人的编号一定是(M–1)%N。例如在13个人中,若报到3的人出列则第一个出列人的编号一定是(3–1)%13=2,注意这里的编号是从0开始的因此编号2实际对应以1为起点中的编号3。根據前面的描述m的前一个元素(M–1)已经出列,则出列1人后的列表如下:

根据规则当有人出列之后,下一个位置的人又从0开始报数则以上列表可调整为以下形式(即以M位置开始,N–1之后再接上0、1、2……形成环状):



通过上表的转换,将出列1人后的数据重新组织成了0~(N–2)共N–1个人的列表继续求N–1个参与人员,按报数到M–1即出列求解最后一个出列者最初在圆形队列中的编号。
看出什么规律没有通过┅次处理,将约瑟夫环问题数学结论的规模缩小了即对于N个人报数的约瑟夫环问题数学结论,可以分解为先求解(N–1)个人报数的子约瑟夫环问题数学结论;而对于(N–1)个人报数的子约瑟夫环问题数学结论又可分解为先求[(N-1)-1]个人报数的子约瑟夫环问题数学结论,……
約瑟夫环问题数学结论中的规模最小时是什么情况?就是只有1个人时(N=1)报数到(M–1)的人出列,这时最后出列的是谁当然只有编号為0这个人。因此可设有以下函数:
那么,当N=2报数到(M–1)的人出列,最后出列的人是谁应该是只有一个人报数时得到的最后出列的序号加上M,因为报到M-1的人已出列只有2个人,则另一个出列的就是最后出列者利用公式【2】,可表示为以下形式:

根据上面的推导过程可以很容易推导出,当N=3时的公式:
于是咱们可以得到递推公式:
有了此递推公式,可使用递归方法来设计程序:
最后出列的人的编号為(从0开始编号):12

使用递归函数会占用计算机较多的内存当递归层次太深时可能导致程序不能执行,比如64层的汉诺塔需要计算很长的時间

}

我要回帖

更多关于 约瑟夫环问题数学结论 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信