Josephus问题
在罗马人占领乔塔帕特后,39个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3个人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。Josephus想了一个办法,帮助自己和朋友逃过了这场死亡游戏。
这里使用循环链表实现,survivor方法,参数n表示围成圈的人数(0~n-1),编号为m的人将被杀死。输出结果是被杀死人的顺序。Java代码如下:
public class Josephus {
private final int n;
private final int m;
private Node first;
private Josephus(int n, int m) {
if (n < 0 || m < 0 || n <= m)
throw new IllegalArgumentException();
this.n = n;
this.m = m;
first = new Node(0, null);
Node pre = first;
for (int i = 1; i < n; i++) {
pre.next = new Node(i, null);
pre = pre.next;
}
pre.next = first;
}
private static class Node {
int no;
Node next;
Node(int no, Node next) {
this.no = no;
this.next = next;
}
}
public static int survivor(int n, int m) {
Josephus josephus = new Josephus(n, m);
Node first = josephus.first;
while (first != first.next) {
int m0 = m;
int m1 = m - 1;
Node pre = first;
while (--m0 > 0) {
first = first.next;
}
if (m1 == 0) {
Node tail = pre;
while (pre.next != tail)
pre = pre.next;
} else
while (--m1 > 0)
pre = pre.next;
System.out.print(first.no + " ");`此行代码表示被杀死的人的序号
first = first.next;
pre.next = first;
}
return first.no;
}
public static void main(String[] args) {
System.out.println(Josephus.survivor(41, 3));
}
}
输出结果:2 5 8 11 14 17 20 23 26 29 32 35 38 0 4 9 13 18 22 27 31 36 40 6 12 19 25 33 39 7 16 28 37 10 24 1 21 3 34 15 30