题目
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
思路
约瑟夫问题: N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
问题转换:
从8
个人开始,每次杀掉一个,去掉被杀的人,然后把被杀的那个人之后的第一个人作为开头继续编号
最后模拟看到,当只剩一个人的时候,编号必定为0
!
最终活着的人编号的反推: 现在知道了G
的索引号的变化过程,那么反推一下 从N = 7
到N = 8
的过程,思考如何才能将N = 7
的排列变回到N = 8
先把被杀掉的C
补充回来,然后右移m
个人,发现溢出了,再把溢出的补充在最前面,经过这个操作就恢复了N = 8
的排列了
因此可以推出递推公式f(8,3)=[f(7,3)+3]%8
进行推广泛化,即f(n,m)=[f(n−1,m)+m]%n
加上初始状态: f(n,m) = 0
java代码如下:
class Solution{
public int lastRemaining(int n, int m){
int pos = 0;
for(int i = 2; i <= n; i++){
pos = (pos + m) % i;
}
return pos;
}
}