约瑟夫问题,过程推理,递归

来源:互联网 发布:中国报学史读后感知乎 编辑:程序博客网 时间:2024/05/17 01:44

约瑟夫问题描述:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列,(来自百度百科)。一般题会让我们求出最后一个人几号;


先举一个简单的例子吧:  

                                                                           

如上图从1到10围城的圆圈,没个一个数去掉一个,问最后那个数被留了下来;

我们可以简单模拟一下期初先消去2,依次为:4,6,8,10,3,7,1,9,于是最后剩余了5号,


我们可以设T[n]表示当有n个数围城一个圈,最后剩余的那个数就是T[n],然后我们开始模拟,推理。

先把n(1...10)给推出来吧:

         

可以看出来T[n]总是奇数,因为我们在绕第一圈的时候就已经把所有的偶数给去掉了,不信自己可以模拟一番,

既然第一轮去掉的都是偶数,那么我们可以利用这个结论,假如我们假设有2n个数,经过第一轮去掉之后,那么毋庸置疑就只剩下奇数了,那么3号就是第二轮的第一个要去掉的。而T[2n]又可以由T[n]这个过程推出来,2n的第二轮开始的数就相当于n的第一轮开始的数的二倍减一,依次类推我们可以得出:T[2n]=2T[n]-1;

我们可以根据这个推论快速推出T[20]=  2*T[10]-1  =  2x5-1  =  9;


但是我们并没有推出更为简单的结果,并不满意,我们根据找出来的这个规律再写出多一点例子:


乍一看,这么多数哪有什么鬼规律,其实仔细一看还是有的,有一个递增(d=2)的循环节数列,为了容易分辨请看下表,每组循环节我用不同的颜色给标记了:


神奇吧,然后我们再来推论,T[n](n->+oo)的情况;

我们要推出这个循环节出现的情况,然后对应每个单独的循环节求值,就简单了。

然后我们开始讨论循环节,(这里说循环节可能不合适,但是我没有找到一个合适的词语形容,大家知道我要表达的意思就好,怪我才疏学浅),我们以n为例;

第一个循环节:1

第二个循环节:2,3

第三个循环节:4,5,6,7

第四个循环节:8,9,10,11,12,13,14,15

第五个循环节:16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31

.......


有没有发现,每个循环节都是以一个2的次方开始并且以一个2的次方减一结束,如:

第一个循环节是:[2^0,2^1),          (左闭右开哦)

第二个循环节是:[2^1,2^2),

第三个循环节是:[2^2,2^3),

......

第N个循环节是:[2^(N-1),2^N);


聪明的小伙伴想必现在已经有答案了,但是鄙人眼拙,还要做一下计算,回归一开始的T[n];

那么现在当n=6时,我们可以直接找到开始的循环节是4,所以n=6是在本循环节的m=(6-4+1)=3位,再用等差数列求和公式即:T[6]=   d*(m-1)+1   =2*2+1=5;

同样的当n=100时,我们可以立刻求出,实在64循环节的(100-64+1)=37位,然后T[100]=2*36+1=73;

然后一般式就是:  T[n] = 2*(n-m)+1;(m可由上述的n=100或者n=6的出)

注:m要根据n来定,可以存一个数组,因为2的32次方已经超大了,所以不会影响时间复杂度;


那么现在这个问题已经解决了,但是关于这个问题还有一个更加神奇的推广(我从一本神奇的书上看到过),有兴趣的小伙伴可以继续往下看:

在求解的过程中,我们发现2的幂起了很重要的作用,所以自然要来研究n和T[n]的以2为基数的表示即二进制。


然后经过一系列的转化......具体的过程我忘了,我只记住了结果,就是n的二进制,最高位的那个数放到最低位,比如n=6时,n=(110)
₂,然后我们把最高位放到最后得n=(101)₂,然后再算二进制,1*2^2 + 0*2^1 + 1*2^0 = 5;

显然答案是对的,再举个例子吧,当n100时,n=(1100100)₂,然后最高位的1放在最后得:n  =  (1001001)₂;

最后结果经过计算得:64+8+1  =  73;   可以证明答案是对的,所以我们可以套上面的公式,也可以用二进制的方法求解;


也许你对上面的解释有疑问,就是为什么要把二进制的最高位放在最后呢,这个我也没法对你做出正规的解释,但是我又找到了另一个不改变最高位的方法,还拿n=6时为例吧,n=(110)₂ = 1*2^2 + 1*2^1 - 1*2^0 = 4 + 2 - 1 = 5;

再如:n=100时,n=(1100100)₂=2^6 + 2^5 - 2^4 - 2^3 + 2^2 - 2^1 - 2^0 =64+32-16-8+4-2-1 = 73;

这个结果是对的,也不需要进行二进制最高位的转换,所以我们可以得出T[n]结果就是n的对应二进制,位为1就加位为0就减,这个结果就很容易算出来了,虽然很神奇,但是我还是比较喜欢我的推出来的那个解法;


当然我相信约瑟夫还有后续,还有很长的路,但是我不能就此止步,去学更多新知识了;

原创粉丝点击