题目:0,1,2,...,n-1这n个数字排成一个圈,从数字0开始每次从这个圆圈中删除第m个数字。求出这个圆圈里剩下的最后一个数字。

分析:利用环形链表模拟圆圈。总共有n个结点,每次都在这个链表中删除第m个结点。实现如下:

int LastRemaining(unsigned int n,unsigned int m)
{
    if(n<1||m<1)
        return -1;
        
    unsigned int i=0;
    
    list<int> numbers;
    for(i=0;i<n;i++)
        number.push_back(i);
    list<int>::iterator current=numbers.begin();
    while(numbers.size()>1)
    {
        for(int i=1;i<m;i++)
        {
            current++;
            if(current==numbers.end())
                current=numbers.begin();
        }
        list<int>::iterator next=++current;
        if(next==numbers.end())
            next=numbers.begin();
            
        --current;
        numbers.erase(current);
        current=next;
    }
    return *(current);
}

另一种简洁的方法,通过观察发现规律。设f(n,m)表示每次在n个数字中每次删除第m个数字最后剩下的数字。发现规律f(n,m)=[f(n-1,m)+m]%n,n>2.n=1时,f(n,m)=0.因此实现如下:

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