约瑟夫环问题

约瑟夫环是一个数学的应用问题:已知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();
}

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

如有问题,欢迎指正

posted @ 2014-09-22 17:36  tjuzjf  阅读(200)  评论(0编辑  收藏  举报