约瑟夫问题 求解过程的另一种容易理解方式

来源:互联网 发布:视频照片拼接软件 编辑:程序博客网 时间:2024/06/05 22:40

从华为在重邮的一道机试题开始:

典型的一道约瑟夫问题;

网上讲的求解过程是这样的:

(参考链接:  1:百度百科 约瑟夫问题http://baike.baidu.com/view/213217.htm?fr=aladdin 

        2:          http://www.cnblogs.com/EricYang/archive/2009/09/04/1560478.html

在n个人时 编号 0 1 2 ... n-1,从0 数到 m-1,数到m-1的人出列,则本次出列的人编号为 (m-1)%n,

则下次从 m%n开始重新计数,剩下的n-1个人构成环 m%n  (m+1)%n  ... (n-1)  0 1 ...(m-2)%n,

由于它们从1重新开始计数,则有它们新的序号为       0            1               ...                  n-2,

设在 旧的环(长度为 n)那个人中的编号为 x'',在新的环(长度为n-1)该人的编号为 x,则由x推得x"的递推式为 x" = (x+m)%n,

即如果我们知道 n-1个人时最终留下的人编号为 f[n-1],则 该人在n个人的环中编号为 f[n] = (f[n-1] + m)%n.又已知n=1时 f[1] = 0,由此可以反向求得 f[n];

写成代码形式为:

        int x=0;        for(int i=2;i<=n;i++){ //i代表当前活着的人数            x = (x + m)%i;        }

注意最终输出时如果起始编号为1,即n个人编号为 1 2...n时,需要令上面计算出的 x +=1;

 

个人觉得上述理解方式不是很容易理解,以下给出个人的一种较容易接受的求解理解方式。

已知 只有1个人即n =1,时 留下的人编号显然为 0,

那么2个人时即    n =2,时对应确定的m,留下的人是不是确定唯一的呢。假设m =10,可以自己数一下,一定是编号为1的人第一个出列,剩下编号为0的人。

递推关系:对应n个人,找到第一个出列的人,显然为 (m-1)%n;则转换为问题规模为n-1时,起始人旧编号为 m%n,新编号为0,如果已知n-1人时问题解为x(指从0开始的编号为x),则其在n个人的问题中旧编号为 x'' = (m+x)%n;

上图如下:

根据其n 由小到大的递推过程可以有如下表达式:

f[n] = ( (m-1)%n + 1 + f[n-1] ) % n,

即 f[n] = (f[n-1] + m) % n;

由此递推式可以写出同上代码。

0 0