您的位置:首页 > 其它

约瑟夫环问题的两种解决方式(递归求解和数组模拟求解)

2016-06-19 13:03 323 查看
约瑟夫环问题各位Acmer肯定都遇到过,就是给你编号为从0~n-1的n个人,从头开始报数,报到m的人离场,问最后留下的人是几号。有两种方法解决这个问题

第一种:数组模拟

这种方法没什么好说的,就是模拟报数和离场的过程,加个访问数组标记一下谁离场了就好了

package HomeWork;

public class JosephRing1 {

public static int josephring(int a[]){

int vis[] = new int [17];
int ans = 0;
int cnt = 0;
int i = 0;
while(true){
if(i == 17){
i = 0;
}
if(vis[i] == 0){
cnt++;
if(cnt % 3 == 0){
vis[i] = 1;
ans++;
System.out.printf("第%d次离开的人是:%d\n",ans,a[i]);
if(ans == 16)
break;
}
}
i++;
}
for(i=0;i<17;i++){
if(vis[i] == 0)
break;
}
return a[i];
}

public static void main(String [] args){

int ans = 0;
int a[] = new int [17];
for(int i=0;i<17;i++){
a[i] = ans++;
}

System.out.println("最后留下的是:" + josephring(a) + "号");
}

}




第二种:递归求解

感觉数组模拟实在low的一批,所以还有一种数学思想的求法;

我们通过写几组简单数据来发现一些规律,比如有6个人,他们编号分别是0,1,2,3,4,5,规定数到3的人离开,那么首轮离开的是2,5,第二轮离开的是3,也就是说离开人的编号是(m-1)%n,下一轮编号为0的人是(m + 0)%n,下一轮编号为1的人是(m+1)%n,则下一轮编号为i的人是(m+i)%n。我们设函数X(n)表示n个人中离开的人,则根据关系有X(n) = (m+X(n-1))%n,那么我们就得到了一个递归表达式,终止递归的条件是x(1),x(1) = (n+m-1)%n。

package HomeWork;

public class JosephRing2 {

public static int josephring2(int n,int m,int i){

if(i == 1){
return (n + m-1) % n;
}
else{
return (josephring2(n-1,m,i-1) + m) % n;
}
}

public static void main(String [] args){

for(int i=1;i<=16;i++){
System.out.printf("第%d次离开的人是:%d\n",i,josephring2(17,3,i));
}
System.out.printf("最后留下的人是:%d\n",josephring2(17,3,17));
}
}



可以看到结果是一样的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  约瑟夫环 算法