约瑟夫环问题的两种解决方式(递归求解和数组模拟求解)
2016-06-19 13:03
323 查看
约瑟夫环问题各位Acmer肯定都遇到过,就是给你编号为从0~n-1的n个人,从头开始报数,报到m的人离场,问最后留下的人是几号。有两种方法解决这个问题
第一种:数组模拟
这种方法没什么好说的,就是模拟报数和离场的过程,加个访问数组标记一下谁离场了就好了
第二种:递归求解
感觉数组模拟实在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 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)); } }
可以看到结果是一样的
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法