约瑟夫环问题

Posted disdader

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了约瑟夫环问题相关的知识,希望对你有一定的参考价值。

题目描述

约瑟夫问题是一个非常著名的趣题,即由n个人坐成一圈,按顺时针由1开始给他们编号。然后由第一个人开始报数,数到m的人出局。现在需要求的是最后一个出局的人的编号。

给定两个int nm,代表游戏的人数。请返回最后一个出局的人的编号。保证n和m小于等于1000。

测试样例:
5 3
返回:4
















据说著名犹太历史学家Josephus在罗马人占领了乔塔帕特之后,39个犹太人与Josephus及他的朋友躲到山洞,39个犹太人决定宁愿死都不要被敌人抓到,于是决定了一种自杀的方式,41个人排成一个圈子,
由第一个人开始报数,报到3的人就自杀。然后再由下一个人开始重新报1,报到3的再自杀,这样再一直下去,直到最后一个人,那个人就可以自己决定自己的命运。这就是著名的约瑟夫问题。

那么怎样才能决定自己的命运呢?就是一开始41人时就要占据有利的位置。那么哪个位置是有利的位置? 不说了,直接上代码!

此方法比较字节用数组模拟环形链表,在一个一个删除节点:
class Joseph {
public:
    int getResult(int n, int m) {
        vector<int> a(n);
        int cur = 0;
        int pre = n-1;
        int count = 0;
        int allPeopleCount = n;
        int i;
         
         
        for(i = 0; i < n-1;i++){
            a[i] =  i+1;
        }
         
        while(allPeopleCount){
         
            if(++count >= m)
            {
                allPeopleCount--;
                count = 0;
                a[pre] = a[cur];    //类似指针
                 
            }  
            else
                pre = cur;
            cur =  a[cur];
        }
             
        return cur+1;
         
         
    }
};

 

另一种方法就是找出递归的关系式我们已知递归的出口是getResult(1,m) = 1;  m代表报到那个数字自杀的人

通过推到我们可以知道 getResult(i,m) = (getResult(i-1,m)+m-1)%i+1; 这是用递归就很简单了。

//#define a[i] (a[i-1]+m-1)%i+1
 
class Joseph {
public:
    int getResult(int n, int m) {
         
        if(n == 1)
            return 1;
        return (getResult(n-1,m)+m-1)%n + 1;
    }
 
          
};

  

以上是关于约瑟夫环问题的主要内容,如果未能解决你的问题,请参考以下文章

约瑟夫环问题

约瑟夫环问题

用单向循环链表实现约瑟夫环问题

约瑟夫环问题

约瑟夫环问题

java中约瑟夫环代码实现