约瑟夫环问题的一般思路

本文介绍了约瑟夫环问题的解决思路,主要通过数学归纳法来探讨。首先解释了问题背景,然后详细阐述了数学归纳法的解题步骤,包括特殊情况下(m=2)的快速计算方式。最后,总结了当m=2时,对于不同n值的解决方案。

 

题目

     n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。


思路:

这个是非常典型的问题,别人都叫他约瑟夫环问题。

(1)比较简单的思路是模拟这个过程,用一个数字去模拟这个过程,每次都删掉一个数据,或者是记录一下。

(2)数学归纳法,或者叫做动态规划的东西来做,

       


(2):数学归纳法:

         首先,第一个被删除的数据假设为k=(m-1)%n, 那么删除后数据为 0,1,2······k-1,k+1,k+2······n-1;

         然后我们会重新从k+1开始计数,开始数。那么我们是不是可以讲数据重新排序一下:

         k+1,k+2······n-1,0,1,2······k-1。

        也就是说讲删除后的数据向右边循环移动(n-k-1),也就是说,移动后的序列和原本的序列的对应关系是:

        f(x)=(x+n-k-1)%n,   x 是原本的位置,发f(x)是计算后的位置。

       那么,反过来,f`(x)=(x+k+1)%n。 也就是说移动后映射到移动前的函数是这个。

      假设,移动前最后剩下的一个数字的位置函数是f(n,m),移动最后剩下的一个数字位置是f(n-1,m)

       那么:f(n,m)=(f(n-1,m)+k+1)%n;

      当n=1的时候,显然f(1, m)=0;

      所以有:

     n=1;f(1,m)=0;

     n>1:   f(n,m)=(f(n-1,m)+k+1)%n

    所以这个就是数学归纳法,根据前面删除一个元素之后的位置,计算出删除元素之前的位置。

   而 k=(m-1)%n

   所以代入后,可以得到:

     n=1;f(1,m)=0;

     n>1:   f(n,m)=(f(n-1,m)+m)%n


所以代码如下:

    int LastRemaining_Solution(int n, int m)
    {
         if(n<1||m<1)
             return -1;
        int result=0;
        for(int i=2;i<=n;i++){
            result=(result+m)%i;
        }
        return result;
    }

 参考文献:http://zhedahht.blog.163.com/blog/static/2541117420072250322938/


  特例:   

        当m=2的时候,可以有其他的更快的计算方式,下面的k和上面的k没有关系,下面的k仅仅表示一个正整数

       当m=2的时候,并且当 n=2^k的时候,也就是数的个数是2的指数倍的时候

       第一轮,从前到后,一共会删除 n/2=2^(k-1)个数,同时0还是会作为计数的起点。这个时候剩下的个数n=2^(k-1)

       第二轮,从前到后,删除 n/2=2^(k-2)个数 ,0 还是会作为计数的起点,这个时候还剩下 n=2^(k-2)个。

       ···

       第 k-1轮,这个时候会剩下  n=2^(k-(k-1))=2^1

       第 k   轮  只剩下 0 这个最初的起点。

      所以,当,m=2,切n=2^k的时候,最后剩下的数一定是0;  

  1.       当,n= 2^k+l < 2^(k+1)的时候怎么办。好办,这个时候第一轮删掉l个数就可以了。这个时候就剩下了 n= 2^k个数了

      所以,这个时候删掉l个数后第一个数将会一直在每一次的删数的过程中存活下来,也就是最终的数

      这里简单的证明一下,第一轮可以删掉的个数大于l个:

  •                                ∵  n= 2^k+l < 2^(k+1) 
  •                                ∴  l<2^k
  •                                 而 第一轮删掉的个数为:n/2=2^(k-1)+l/2;
  •                                 ∵ l<2^k   => 2^(k-1)>l/2
  •                                 ∴  n/2=2^(k-1)+l/2 > l/2 +l/2=l;
  •                                 所以第一轮删掉的元素个数一定是大于 l 个的

     综上,当m=2的时候,f(n,m) 表示最终剩下的数,那么有:

               n=2^k :f(n,m)= 0;

               n=n= 2^k+l:f(n,m)= 2*l;

(n个数的的排列是0,1,2,3,·····n-1)

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值