首页 > 代码库 > 约瑟夫环问题

约瑟夫环问题

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

这是一个经典的算法题,拿到手上,先想到的是模拟报数过程,实现如下(是在cocos2dx环境下,代码中的ccarray可以换成c数组):

int josephus(int n, int m, int k){    CCArray *array = CCArray::create();    for (int i = 0; i < n; i ++) {        array->addObject(CXNumber::create(i + 1));    }        int index = k - 1;        while (true) {                for (int i = 0; i < m; i ++) {                        if (array->count() == 1) {                return ((CXNumber *) array->objectAtIndex(0))->getIntValue();            }                        if (i == m - 1) {                bool changeIndex = (index == array->count() - 1);                array->removeObjectAtIndex(index);                                if (changeIndex) {                    index = 0;                }            }            else            {                index ++;                if (index == array->count()) {                    index = 0;                }            }        }    }}

后来网上搜了一下,看到一个 http://blog.csdn.net/dengyaolongacmblog/article/details/39208675 的实现,恍然大悟,又写了个基于数学归纳的实现,复杂度大大降低,从O(m^n)到O(n), 实现如下:

int anotherJosephus(int n, int m, int k){    CCArray *array = CCArray::create();    for (int i = 0; i < n; i ++) {        array->addObject(CXNumber::create(i + 1));    }        int index = k - 1;        for (int i = 0; i < n - 1; i ++) {        index = (index + m) % array->count(); //数学归纳得出要被淘汰的index        index --;                if (index < 0) {            index = array->count() - 1;        }        array->removeObjectAtIndex(index);    }        return ((CXNumber *) array->objectAtIndex(0))->getIntValue();}

以上两种代码,都已测试过

如有问题,欢迎指正

约瑟夫环问题