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

来源:互联网 发布:pdf生成器软件 编辑:程序博客网 时间:2024/05/22 03:25

约瑟夫环问题各位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));}}

可以看到结果是一样的

0 0