题目描述:
把0 ,1 ,……, n-1这n个数排成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字。
求这个圆圈剩下的最后一个数字
示例:
输入:n=3,m=2,即把0 ,1 ,2这三个数字每次删除第二个,删除的依次为1, 0,剩下2
输出:2
分析:
经典解法,用环形链表模拟圆圈。当链表中只有一个节点时,退出。但是这种方法空间复杂度较高
更高效的解法,分析其中的数学规律。
在n个数字中,第一个被删除的是 k = (m-1)%n
在删除k个,剩下的n-1个数字为:0, 1 ,…… ,k-1 ,k+1 , ……, n-1
然后新一轮的计数从k+1开始,即k+1为第一个数字,形成 k+1 , …… ,n-1 ,0 , 1 ,…… k-1。剩下的数字也是n和m的函数。
将剩下的n-1个数字作一个映射:
将映射定义为p,则p(x) = (x-k-1)%n。该映射的逆映射为f(x)=(x+k+1)%n。
映射后的序列和最初的序列具有相同的形式,只是元素个数变为了n-1.
因此可得到递推公式:
代码:
int lastRemain(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;
}