约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人会被杀死;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到剩下一个人生存。
n = 9,k = 1,m = 5 【解答】
出局人的顺序为5,1,7,4,3,6,9,2,8。
题目引用了 百度百科 http://baike.baidu.com/view/717633.htm
当然,我们最关心的是最后的那个输出——不死的位置
这个题目我自己先做出了一个O(N^2)的,相信许多人都能直接地想到
package algorithm; import java.util.LinkedList; public class Josephus { LinkedList<Integer> list = new LinkedList<Integer>(); private int n; private int k; private int m; public Josephus(int n, int k, int m){ this.n = n; this.k = k; this.m = m; for(int i=1;i<=n;i++){ list.add(i); } } //1...n, 从K位置开始数起(K是1),数到M,移除一个 public void print(){ while(n>0){ int pos = getPos(n,k,m); System.out.print(list.remove(pos-1)); n--; k = pos; } } //存在数学计算,指定N,K,M可以知道排第几的要被移除 private static int getPos(int n, int k,int m){ m = (m%n==0)? n : m%n; k = (k%n==0)? n : k%n; if(k-1+m<=n){ return k-1+m; }else{ return (k-1+m)-n; } } public static void main(String[] args){ new Josephus(9,1,5).print(); } }
输出和百度百科的结果一样
接下肯定是找O(N)的,当时我觉得自己不可能想得到的了,就直接GOOGLE,结果百度百科的推导根本不是推导,直接抄来的公式F(N) = (F(N-1)+M)%N,而WIKI的推导,看不懂,还看到一种是分奇数和偶数的数学推导,更难看懂,ORZ,于是自己在纸上面画一画,罗列一些情况,看看找不找得到规律
结果真的找到规律了
假设N个人编号是从0到N-1,并且考虑没有K的情况,都是从0号的人开始数,数到M的人会被干掉。F(N,M)代表生存下来的那个人的编号。
在纸上罗列M=5的情况时候,发现F(N)的问题,在杀掉一个人之后,完全可以转化成F(N-1)的问题——这太像动态规划了!
于是产生了以下算法
f(n)表示的意思是
0...n-1个人,从0开始数,0号数1,1号数2..数到N的那个人会被杀掉。被杀掉的人之后的人数1,后面的接着数2...这样后面只会剩下一个人,f(n)的返回值就是这个人原来的编号。
g(n),其实为了适应题意对f(n)的结果做转化,N个人的编号为1到N,并且新增一个参数表示从第K个人开始数,而不一定是第一个人。
我们程序输出的是8,与结果一致,暂时正确!
int firstKilledPos = (m-1)%i
推导过程如下
f(n) = ((m-1)%n + 1 + f(n-1))%n = (m%n + f(n-1))%n = (m+f(n-1))%n
正确程序的f(n,m)使用了
f(n) = ((m-1)%n + 1 + f(n-1))%n,
有N个人时,(m-1)%n表示的第一个被杀掉的人的位置,(m-1)%n + 1 + f(n-1)表示,根据N-1时已经计算的存货的位置,以被杀的人位置为原点,得到最后存活的人的位置,((m-1)%n + 1 + f(n-1))%n则表示如果位置大于N则取模。
而f2(m,n)使用了
(m+f(n-1))%n
正确的程序
package algorithm; import java.util.LinkedList; public class FastJosephus { public static int f(int n, int m){ int[] res = new int[n+1]; res[1] = 0; for(int i=2;i<=n;i++){ int firstKilledPos = (m-1)%i; int livePos = res[i-1]; res[i] = ((firstKilledPos+1)+livePos)%i; } return res[n]; } public static int f2(int n, int m){ int[] res = new int[n+1]; res[1] = 0; for(int i=2;i<=n;i++){ res[i] = (res[i-1]+m)%i; } return res[n]; } public static int g(int n,int k ,int m ){ return (f(n,m)+(k-1))%n + 1; } public static int g2(int n,int k ,int m ){ return (f2(n,m)+(k-1))%n + 1; } public static void main(String[] args){ System.out.println(g(7,1,4)); System.out.println(g2(7,1,4)); } }
相关推荐
在C语言中,实现约瑟夫环问题通常有多种方法,本文章中介绍了三种不同的C语言解答方法,但详细内容并未完全给出。不过,从给出的内容和描述中,我们可以提取出以下知识点: 1. 算法思路:采用数学归纳法和递推关系...
这个题我是用数组下标置0方法做的,类似单链表的性质,这个方法是模拟了游戏过程,是比较笨的代码,喜欢研究的朋友可以...时间复杂度为O(n^2),代码注释很详细,基本每一行我都写了注释,稍微有点基础的就可以看的懂
约瑟夫环问题的算法时间复杂度为O(n),空间复杂度为O(1)。这意味着算法的时间和空间消耗都相对较低,特别是空间复杂度,它仅需要一个变量来记录当前报数的位置,这使得算法非常适合处理大规模数据。 除了上述基于模...
最后是**约瑟夫环问题**,这是一个基于循环链表的算法问题。假设有一群人围成一个圈,从某个人开始报数,报到特定数值的人将被淘汰,然后从下一个人继续报数,直至剩下最后一个人。约瑟夫环问题的解决通常使用模运算...
综合来看,整个算法的复杂度为O(n^2),这是由于每次删除操作都可能需要遍历整个线性表。 在实际的调试过程中,可能会遇到的问题主要是如何正确计算出下一个报m的人的下标,这里利用了模运算来解决这个问题。经过...
从性能分析的角度看,解决约瑟夫问题的算法时间复杂度为O(n),其中n是人数,这是因为每个节点最多被访问一次。空间复杂度为O(1),由于我们在解决问题的过程中,只使用了有限的几个指针变量,并没有随着人数的增加而...
首先,我们来看第一个算法问题——换钱的方法数。这是一个典型的动态规划问题,要求计算在给定面值的货币集合中,组成特定金额的不同组合数。通过自底向上的动态规划状态转移,我们可以求解出目标金额的所有可能组合...
约瑟夫环 leetcode algorithm-learn-start 总结 一、什么是链表? 1.和数组一样,链表也是一种线性表。 2.从内存结构来看,链表的内存结构是不连续的内存空间,是将一组零散的内存块串联起来,从而进行数据存储的...
首先,猴子选大王,又称为“约瑟夫环”问题,是一个典型的链表操作问题。在这个问题中,一群猴子围成一个圈,每隔一定数量的猴子就会被剔除,直到只剩下一只猴子成为大王。解决这个问题通常使用循环链表,通过模拟...
这里可以使用Floyd的“约瑟夫环”算法,它能够有效地解决这类问题,时间复杂度降低到了O(n)。 约瑟夫环算法的关键在于其循环数组的实现。我们可以创建一个数组,大小等于猴子的数量,数组中的每个元素代表一只猴子...
北邮数据结构实验一的核心是通过解决尤瑟夫问题(也称为约瑟夫问题),帮助学生深入理解循环链表的结构及其在算法设计中的应用。尤瑟夫问题是一个著名的理论问题,它不仅在数学领域有着广泛的应用,也在计算机科学的...
1475 Ranklist 没有完美解决,不知道您有没有好方法…… 1572 Bracelet 题义不明,感觉可能是判定欧拉回路的存在性,但是过不去 1133 Smith Numbers 没有完美解决,数学 1080 Direct Subtraction 尚未解决,我过的...
《漫话数据结构-猴子选大王》是一个有趣的数据结构应用问题,通常称为“约瑟夫环”或“猴子选大王”。这个问题描述了一个虚拟的猴子选举过程,通过一定的淘汰规则来确定大王。在这个过程中,我们可以看到数据结构在...
5. **约瑟夫环问题**:这是一个经典的算法问题,使用链表可以方便地解决。单向链表上的约瑟夫环问题涉及将人围成一圈,按顺序报数,报到特定数字的人出圈,直到只剩一人。链表可以模拟这个过程,通过调整节点间的...
从提供的部分内容来看,文档包含了多个常见的编程和算法问题及其解决方案的概述,这些题目涵盖了数据结构和算法的多个方面,例如数组、链表、二叉树、字符串操作等。下面将详细介绍文档中提到的每个知识点: 1. 二...
1475 Ranklist 没有完美解决,不知道您有没有好方法…… 1572 Bracelet 题义不明,感觉可能是判定欧拉回路的存在性,但是过不去 1133 Smith Numbers 没有完美解决,数学 1080 Direct Subtraction 尚未解决,我过的...
此外,还提供了按内容查找、插入、删除元素以及链表逆置和约瑟夫环问题的解决方法。 接着是栈的操作。栈是一种后进先出(LIFO)的数据结构,常用于括号匹配等任务。程序中展示了如何创建堆栈,执行进栈和出栈操作,...
这段代码实现了约瑟夫问题的基本逻辑,即从一个编号为1至n的环形队列中,按照特定规则(如步长m)逐个移除队列成员,直到队列为空。使用了一个临时数组`p`来保存原始序列,通过循环和索引调整实现成员的移除和重新...