圆圈中最后剩下的数字
0,1,2,3…n-1共n个数字排成一圈,从数字0开始依次删除第m个数字。求最后剩下的数字。
思路:常规做法是就环形链表,可以用数组表示。这里介绍一种数学方法来解这类约瑟夫环问题。
f(n,m)表示n个数字(0,1,2,3…n-1)删除第m个数字最后剩下的数字。
分析:第一个删除的数字为(m-1)%n,记作k.剩下的数字(k+1,k+2…n-1,0,1,2…k-1).
剩下的n-1个数字最后剩下的数字也是f(n,m),所以存在映射关系:f(n,m) = g(n-1,m)
g(n-1,m) ---> f(n-1,m)
k+1 —> 0
k+2 —> 1
……..
n-1 —> n-k-2
0 —> n-k-1
1 –> n-k-2
………
k-1 —> n-2
从g(n-1,m)到f(n-1,m)的映射关系:p(x) = (x-k-1)%n
该映射的逆映射是:p-1(x) = (x+k+1)%n
f(n,m) = g(n-1,m) = p-1[f(n-1,m)] = [f(n-1,m)+k+1]%n = [f(n-1,m)+m]%n
因此:
f(n,m) = 0 ……………… (n ==1)
(f(n-1,m)+m)%n …… ( n>1)
参考代码:
root@gt:/home/git/Code# ./a.out lastOne:87
root@gt:/home/git/Code# cat lastOne.c #include <stdio.h>
int lastOne(int n,int m)
{
if(n < 1 || m < 1)
return -1;
int last = 0;
for(int i = 2;i < n;++i)
last = (last + m)%i;
return last;
}
int main()
{
int res = lastOne(100,3);
printf("lastOne:%d\n",res);
}