1 题目及要求
1.1 题目描述
1、0, 1, 2,……, n-1这n个数排成一圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
2、一个长度为n的数组,每次数组里删除第m个数字(到末尾后从头开始),求最后删除的一个数字。
2 解答
2.1 题目分析
1、首先定义方程f(n, m),表示每次在这n个数字0, 1, 2, ……, n-1中删除第m个数字最后剩下的数字。下面我们来求出递推关系:
在这n个数字中,第一个被删除的数字是(m-1)%n,记该数为k,那么剩下的数字为0, 1,2, ……, k-1, k+1, ……, n-1,并且下次删除的数字从k+1开始计数。因为他们是循环的,因此可以这样排列效果是一样的:k+1, ……, n-1, 0, 1, 2, ……, k-1。且他们可以表示为(k+1+i)%n,其中i对应为0, 1, 2,……, n-2。因此这剩下的n-1个数最后剩下的数就可以表示为(f(n, m)+k+1)%n。
于是有:
这样就可以用递归或循环实现。
2、由1求出对应的下标,然后就解决了。
2.2 代码
unsigned indexLastRemaining(unsigned n, unsigned m){
if(n<1 || m<1) return 0;
unsigned last = 0;
for(unsigned k1(1);k1!=n;) last = (last+m)%++k1;
return last;
}
int numsRemaining(int *v, int n, int m){
if(!v || n<1 || m<1) return 0;
return v[indexLastRemaining(n,m)];
}