使用java的循环单向链表解决约瑟夫问题
2020-12-13 16:02
标签:第一步 规则 罗马 get cycle bsp 需要 地方 使用 据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决? 约瑟夫的故事比较残忍,我们把约瑟夫问题改为一个小游戏,游戏规则如下: 假设编号为1,2,3...n个人手拉手围坐在一圈,约定编号为k(1
首先我们定义一个循环链表,由此来模拟n个人围坐在一圈。下面先看下单链表的实现代码 下面我们用图例的方式讲解一下添加n个节点的循环链表的流程,当创建第一个节点时,我们让first和current指向第一个节点,并将current的next指向first节点,以此来形成一个循环。当添加第二个节点时,我们将current的next指针指向第二个节点,第二个节点的next指向first,然后将current后移,即current指向第二个节点,以此类推。 现在我们问题的第一步即n个人围坐在一起解决了,下面来实现第二步从第k个人开始数数。第二步比较简单,即让first指针后移k-1次,由此让first指针指向第一个数数的人。但由于first指向的节点需要出圈,这里我们再定义一个helper指针,来指向first指针的前一个节点,即让helper指针首先指向first,依此循环直到helper的next指针等于first(因为是循环链表)。并保持helper指针始终在first指针的前一个节点(只有一个节点时与first指针指向同一个节点)。假设k=2即从第二个人开始数,m=3即数到3的人出圈,如下图所示 找到node4的人出圈,这时让helper的next等于first的next,然后让first等于helper的next,如下图所示 继续从node1开始数,数到3,即node3出圈,此时指针指向情况如下图 node3出圈后,下一个要出圈的为node1,依此循环,直到helper与first指针指向相同节点,即node2为最后一个要出圈的人。代码如下 测试代码 测试结果: 以上就是实现约瑟夫问题的循环链表解决思路,当然肯定还有很多别的解决思路,欢迎留言探讨,谢谢。 使用java的循环单向链表解决约瑟夫问题 标签:第一步 规则 罗马 get cycle bsp 需要 地方 使用 原文地址:https://www.cnblogs.com/menglong1108/p/11617542.html什么是约瑟夫问题
使用循环链表模拟n个人围坐一圈
1 /**
2 * 单向循环链表
3 */
4 class CycleSingleLinkedList{
5 PersonalNode first = null;
6 /**
7 * 向循环链表中添加num个节点
8 * @param num
9 */
10 public void add(int num){
11 if(num ){
12 System.out.printf("参数不合法");
13 return;
14 }
15 PersonalNode curr = null;
16 for (int i = 1; i ) {
17 PersonalNode personalNode = new PersonalNode(i);
18 if(i == 1){
19 //添加第一个节点
20 first = personalNode;
21 curr = first;
22 curr.setNext(first);
23 }else {
24 curr.setNext(personalNode);
25 personalNode.setNext(first);
26 curr = personalNode;
27 }
28 }
29
30 }
31
32 }
33
34 /**
35 * 人物节点
36 */
37 class PersonalNode {
38 private int no;
39 private PersonalNode next;
40
41 public PersonalNode(int no){
42 this.no = no;
43 }
44
45 public int getNo() {
46 return no;
47 }
48
49 public void setNo(int no) {
50 this.no = no;
51 }
52
53 public PersonalNode getNext() {
54 return next;
55 }
56
57 public void setNext(PersonalNode next) {
58 this.next = next;
59 }
60 }
1 /**
2 * 约瑟夫问题
3 * @param n n个人围成圈
4 * @param k 第k个人开始报数
5 * @param m 数到m的人出圈
6 */
7 public void joseph(int n,int k,int m){
8 //添加n个人
9 add(n);
10 //helper指针指向first的前一个节点
11 PersonalNode helper = first;
12 while (helper.getNext() != first){
13 helper = helper.getNext();
14 }
15 //找到第k个人
16 for (int i = 0; i ) {
17 first = first.getNext();
18 helper = helper.getNext();
19 }
20 //数到m的人出圈
21 while (true){
22 if(helper == first){
23 break;
24 }
25 for (int i = 0; i ) {
26 first = first.getNext();
27 helper = helper.getNext();
28 }
29 System.out.printf("编号为%d的人出圈\n",first.getNo());
30 first = first.getNext();
31 helper.setNext(first);
32 }
33 System.out.println("最后出圈的人是:"+first.getNo());
34
35 }
1 public static void main(String []args){
2 CycleSingleLinkedList linkedList = new CycleSingleLinkedList();
3 linkedList.joseph(4,2,3);
4 }
总结