首页 > 代码库 > 求圆圈中剩下的最后一个数字
求圆圈中剩下的最后一个数字
n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。求出在这个圆圈中剩下的最后一个数字。
这个问题在wiki上叫约瑟夫斯问题。
一开始的序列是
S(n): n-1, 0, 1, 2, 3, ...., n -2 (一个环)
删除了第k=(m-1)%n个数,之后变成
S‘: n-1, 0, 1,2,...,k-1,k+1,...,n-2
S(n-1): n-2, 0, 1,2,3, ...,n-3
将S(n-1)按照f(x)=(x+k+1)%n 进行映射可以得到S‘,也就是0->k+1, 1->k+2....
将S‘继续删除第k个数,以此类推,最后一个序列,也是可以通过S(1)来映射。
S‘ = (S(n-1) + (m-1)%n + 1) % n = (S(n-1) + m) % n.
那么对于每个序列的最后一个数, 也是满足这个映射。
f(n) = (f(n-1) + m) % n.
当n==1的时候,只有一个数,那么最后一个数肯定就是0,f(1) =0.
然后就可用动态规划去做了。
This approach has running time $O(n)$, but for small k and large n there is another approach. The second approach also uses dynamic programming but has running time $O(k\log n)$. It is based on considering killing k-th, 2k-th, ..., $(\lfloor n/k \rfloor k)$-th people as one step, then changing the numbering.
这里提到的第二种方法为什么会是$O(k\log n)$,没想明白? 把杀掉k-th, 2k-th, ..., $(\lfloor n/k \rfloor k)$-th当个步骤,所以总共需要k步。那也就是说,重新编号的开销是$\log n$.怎么做到的?