题目: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; }