问题描述
有n个孩子,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会出列,然后从第m+1个人开始,重复以上过程。在游戏结束后,问n个孩子的出列顺序?
解决方法
(1)使用环形单链表解决该问题,首先将n个节点连接在一块成为一个环形链表,有第一个节点开始,数到m则删除该节点,然后重新报数,直到链表中只剩下最后一个节点。此时最后一个节点仍然是环形,则仍可报数到m,为最后出列。
(2)使用数组模拟解决
(3)使用递归方法解决
这里采用环形单链表解决。
代码实现(java)
这里创建环形单链表时首先将一个节点加入并构成一个环形,也可以先把所有节点加入,构成一个单链表,再将第一个节点和最后一个节点连接起来。
package com.Josephu;
public class Josephu {
public static void main(String[] args) {
JosephuLinkedList jList = new JosephuLinkedList(5);
jList.josephuList();
jList.showJosephuList();
jList.JossephuGame(2);
}
}
class Children {
private int no;
private Children next;
public Children (int no) {
this.no = no;
}
public int getNo() {
//获取编号
return no;
}
public Children getNext() {
//获取下一个Children节点
return next;
}
public void setNext(Children next) {
//设置下一个Children节点
this.next = next;
}
}
class JosephuLinkedList {
Children first = null;
//Children总个数
private int sum;
public JosephuLinkedList (int sum) {
this.sum = sum;
}
//根据总人数设置环形链表
public void josephuList () {
Children currentChild = null;
for(int i = 1; i <= sum; i++) {
Children child = new Children(i);
if (i == 1) {
first = child;
first.setNext(first);
currentChild = first;
} else {
child.setNext(first);
currentChild.setNext(child);
currentChild = child;
}
}
}
//遍历环形链表
public void showJosephuList () {
Children currentChild = first;
System.out.println("环形链表中的编号为:");
while (currentChild.getNext() != first) {
System.out.println(currentChild.getNo());
currentChild = currentChild.getNext();
}
System.out.println(currentChild.getNo());
}
//计算获取出队序列,count代表报数人序号为count时出队,从1开始
public void JossephuGame (int count) {
// int j =0;
Children helper = first;
Children currentChild = first;
while (helper.getNext() !=first) {
helper = helper.getNext();
}
// while ( j != sum-1) { 也可以用此作循环条件
System.out.println("出队child的编号为:");
while (true) {
for (int i = 1; i <= count - 1; i++) {
currentChild = currentChild.getNext();
helper = helper.getNext();
}
// j++;
System.out.println(currentChild.getNo());
currentChild = currentChild.getNext();
helper.setNext(currentChild);
if (currentChild == helper) {
//此时队伍中只剩一人
break;
}
}
System.out.println(currentChild.getNo());
}
}