约瑟夫问题
N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
解决
(1)链表:用一个循环链表解决。(缺点:时间复杂度为:O(MN))
(2)数学公式
f(n,m)=(f(n-1,m)+m)%m
每杀掉一个人,下一个人成为头,相当于把数组向前移动M位。
若已知N-1个人时,胜利者的下标位置位f(N−1,M)f(N−1,M),则N个人的时候,就是往后移动M为,(因为有可能数组越界,超过的部分会被接到头上,所以还要模N),既f(N,M)=(f(N−1,M)+M)%nf(N,M)=(f(N−1,M)+M)%n
代码:
迭代法
public int lastRemaining(int n,int m)
{
int p=0;
for(int i=2;i<=n;i++)
{
p=(p+m)%i;
}
return p+1;
}
public int lastRemaining(int n, int m){
if(n < 1 || m < 1) {
return -1;
}
if(n == 1) {
return 0;
}
return (lastRemaining(n-1, m) + m) % n;
}