乔瑟夫问题描述:乔瑟夫和他的朋友以及39个犹太人被敌人包围,为了不当俘虏41个人约定围成一个圈然后从1开始报数,每次报数到3的人就壮烈自杀,但是乔瑟夫和他的朋友不想死,问他们应该站在什么位置才能免去一死(答案是16和31)
问题分析:该问题可以看成是循环列表的遍历问题,每当遍历到3的时候就把该节点删除,最后剩下的两个位置就是乔瑟夫和他朋友活下来的位置:
package wh1009;
public class JosePh {
//需要的节点类
private static class Node<T>{
private Node next;
private T item;
//初始化节点
public Node(Node next,T item){
this.item = item;
this.next = next;
}
}
public static void main(String[] args) {
//构建一个长度为41的循环链表
Node<Integer> first = null;
Node<Integer> before = null;
for (int i = 1; i <42 ; i++) {
if(i==1){
first = new Node<>(null,i);
before = first;
continue;
}
Node newNode = new Node(null,i);
before.next = newNode;
before = newNode;
if(i == 41){
before.next = first;
}
}
//记录第一个节点
Node<Integer> n = first;
//记录该节点的上一个节点
Node<Integer> pre = null;
//计数器
int count = 0;
while (n!=n.next){
count++;
if(count == 3){
//移除报数为3的节点,将这个人杀死
pre.next = n.next;
System.out.print(n.item+" ");
//重置计数器
count = 0;
n = n.next;
}
else{
//将节点后移,并且记录上一个节点
pre = n;
n = n.next;
}
}
System.out.print(n.item);
}
}
运行的结果:
3 6 9 12 15 18 21 24 27 30 33 36 39 1 5 10 14 19 23 28 32 37 41 7 13 20 26 34 40 8 17 29 38 11 25 2 22 4 35 16 31
所以最后活下来的是16和31的位置,乔瑟夫和他的朋友只要选择这个位置就可以免去一死