约瑟夫环问题是类似这样的问题:
给你一个序列,编号为1到n,给你一个数m让你从第一个人开始数,数到m就删除这个数。就是这样的问题,一般是问最后一个删除的是哪个。
我了解到得解法有两种:
第一:暴力循环枚举:
时间复杂度是O(n^2)的。
代码:简单模拟,就不上了......................(你咬我)算了,我就不贴了,毕竟这么简单,这都不行那还是用后面个吧
第二:公式推导得到:
时间复杂度O(n)的。(很优秀了)
代码:
int Joseph(int n , int m )
{
int num = 0 ;
for(int i = 2 ; i <= n ; i ++) num = (num + m) % i ;
return num + 1 ;///返回最后删除的那个数
}
就是这样.........
推导过程是:(很重要,不能知其然,不知其所以然)
以问题的形式得出:
N个人(编号0~(N-1)),从0开始报数,报到(M-1)的删掉,剩下的数继续从0开始报数。求最后删掉的编号。
N个人编号如下:
0 , 1 ............ m-2 , m-1,m,..............n-2,n-1,n
第一个删掉的数是(M-1)%N,报到3的数删掉,则第一个删掉的数的编号是(3-1)%41=2。编号(M-1)%N删掉后,剩下的数排列如下:
0 , 1............m-2, ,m,...............n-2,n-1
有数删掉后,下一个位置M又从零开始报数,因此环应该如下:
m,m+1,........n-1,0,1.................m-2
将上面的排列顺序重新编号:
m,m+1,........n-1,0,1.................m-3,m-2
0,1,..............m-2,m-1,m...........n-1,n
问题变为(N-1)个人,报到为(M-1)的人自杀,问题规模减小了。这样一直进行下去,最后剩下编号为0的人。用函数表示:
F(1)=0
当有2个人的时候(N=2),报道(M-1)的人自杀,最后自杀的人是谁?应该是在只有一个人时,报数时得到的最后自杀的序号加上M,因为报到M-1的人已经自杀,只剩下2个人,另一个自杀者就是最后自杀者,用函数表示:
F(2)=F(1)+M
可以得到递推公式:
F(i)=F(i-1)+M
因为可能会超出总人数范围,所以要求模
F(i)=(F(i-1)+M)%i
所以就可以O(n)的求出来了
菜得不一样,菜出新高度!