程序员面试题精选100题(14)-圆圈中最后剩下的数字

题目:n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。

思路:最初有0,1,2,3...m-1,m,m+1,m+2...n-1这么多个数,
第一次以后变成了0,1,2,3...m-1 ,m+1,m+2...n-1

第一个被删除的数字为m%n - 1 记为k (数组的位置需要-1)

而这个时候数组的起始位置发生了变化
k+1----0
k+2----1
...
n-1 --- n-k-2
0  ----  n-k-1
....
x----x-k-1
...
k-1 ---- n-2

所以这个映射为p(x)=(x-k-1)%n;----%n可以体现循环思想
p-1(x)=(x+k+1)%n;----逆运算

设f(n,m)可以计算出最终的结果
f'(n-1,m)为第一次删除后的序列,因为序列和以前不同,但是规则相同
f'(n-1,m)计算的结果经过映射后也可以得到和f(n,m)相同的结果
所以f'(n-1,m)=p-1(f(n-1,m))=[f(n-1,m)+k+1]%n  再把k=m%n-1代入
=[f(n-1,m)+m%n-1+1]%n=[f(n-1,m)+m]%n


当n=1时,也就是序列中开始只有一个数字0,那么很显然最后剩下的数字就是0。我们把这种关系表示为:

         0                  n=1
f(n,m)={
         [f(n-1,m)+m]%n     n>1

//其实非递归的方式容易理解些,实质上就是把余下的n-1个数字入栈,然后再做同样的事情





你可能感兴趣的:(java,数据结构)