约瑟夫环算法
####一个经典的游戏问题:在一片大海上,由于船上的资源不足,不得以必须将一部分人丢掉海里,才能让剩下的人活下来,船长提议大家首位相接凑成一个圆环,船上共有50人,从船长依次从0到1,2,3开始查数,被查到7的人就要被丢到海里,然后被丢到海里的人的下一个人继续从1开始查数,往复操作,直到船上剩下25人为止,那么请问被丢下到海里的人都是哪些人?
首先,我们不妨将这个问题缩小化,看看是否能找出一般的规律,然后进行归纳
我们将这个问题缩小 假设有7个人,每次第4个人被扔到海里,直到剩下最后一个人
最初的人 0 1 2 3 4 5 6
第一次后 0 1 2 4 5 6
第二次后 1 2 4 5 6
第三次后 1 2 4 6
。。。
通过以上的规律我们 可以知道以下
(1)第一次被扔下海的一定是3(也就是4号)
(2)第二次被扔的0(也就是1号),这个0是我们怎么算出来的呢,是(3+4)%7=0
(3)第三次被扔下的是5,(0+4)%6,但是这次我们把已经被丢掉海里的3号重新计算了一次,这就产生了一个不连续的问题,但是怎么办呢,我们不妨将这些不连续的数字设计成一个环,如下所示
标记 0 1 2 3 4 5 6
最初的人 0 1 2 3 4 5 6
标记 3 4 5 0 1 2
第一次后 0 1 2 4 5 6
标记 0 1 2 3 4
第二次后 1 2 4 5 6
这样设计后,我们会发现这些标记每次都是连续的,这样我们每次只对标记做加减,就避免了因删掉数字而有空缺位置的问题了,但是怎么得到实际的被扔到海里的数字呢,仔细观察,我们会发现规律 以第二次为例 新的数字=(旧的数字-4)%6
归纳出以下:
public int dg(int sum,int value,int n){
if(n==1){
return (sum+value-1)%sum;
}else{
return (dg(sum-1,value,n-1)+value)%sum;
}
}