約瑟夫問題,這是一個事關生命的問題。傳說有一天,39個猶太人躲避戰亂逃到了一個洞裏,洞裏還有約瑟夫和他的一個朋友。猶太人呢寧死不屈,爲了不讓敵人抓住,於是發明了一個死亡遊戲。猶太人一致決定,41個人圍成一個圈,從第一個人開始數數,當數到3的那個人呢那個人就刺自己一下,把自己給殺了。比如第1個人開始數數,第3個數到3就自殺,接着第4個開始數1,第6個數到3就自殺……以此類推,直到41個人都殺掉自己。約瑟夫和他的朋友想着不能就這麼輕易的go die,但是猶太人這麼多他們又不能傻BB地奮起反抗。那怎麼辦呢,聰明的約瑟夫想到,不管自殺的順序是怎麼的,最後總會有兩個人剩下。約瑟夫先生略作思考,就把自己和朋友分別排到了第16個和第31個位置,最後39個猶太人呢全都自殺了,剩下了約瑟夫和他的朋友,所有人都達到了自己的目的,皆大歡喜(雖然有點血腥,但是約瑟夫憑藉自己的智慧活了下來)。
import com.sun.nio.sctp.IllegalReceiveException;
public class YueshefuLinked<E> {
private class Node{
public E e;
public Node next;
public Node() {
this(null, null);
}
public Node(E e) {
this(e, null);
}
public Node(E e, Node next) {
this.e = e;
this.next = next;
}
}
private Node head;
private int size;
public YueshefuLinked() {
this.head = null;
this.size = 0;
}
public int getSize() {
return size;
}
public void add(int index, E e) {
if (index < 0 || index > size) {
throw new IllegalReceiveException("add fail. index is illegal");
}
if (head == null) {
head = new Node(e);
head.next = head;
size++;
return;
}
if (index == 0) {
addFirst(e);
} else {
Node cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
Node newNode = new Node(e, cur.next);
cur.next = newNode;
size++;
}
}
public void addFirst(E e) {
if (head == null) {
head = new Node(e);
head.next = head;
size++;
return;
}
Node cur = head;
for (int i = 0; i < size - 1; i++) {
cur = cur.next;
}
Node newNode = new Node(e, head);
cur.next = newNode;
head = newNode;
size++;
}
public void remove(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("remove fail. idnex is illegal");
}
if (head == null) {
throw new IllegalArgumentException("remove fail. linked is empty");
}
if (index == 0) {
removeFirst();
} else {
Node cur = head;
for (int i = 0; i < index - 1; i++) {
cur = cur.next;
}
Node rnode = cur.next;
cur.next = rnode.next;
size--;
}
}
public void removeFirst() {
if (head == null) {
throw new IllegalArgumentException("remove fail. linked is empty");
}
if (size == 1) {
head = null;
size--;
} else {
Node cur = head;
for (int i = 0; i < size; i++) {
cur = cur.next;
}
head = head.next;
cur.next = head;
size--;
}
}
/** 約瑟夫問題
* 首先自定義了一個循環鏈表
*/
public void checkYueshefu() {
Node cur = head;
int i = 1;
while (true) {
if (i == 2) {
Node next = cur.next;
cur.next = next.next;
/*要記住把head的指向改變,不然會一直重1開始打印。*/
head = cur;
i = 0;
size--;
}
i++;
cur = cur.next;
if (size < 3) {
break;
}
}
System.out.println(toString());
}
@Override
public String toString() {
StringBuilder str = new StringBuilder();
str.append(String.format("YueshefuLinked: size = %d, [", size));
Node cur = head;
for (int i = 0; i < size; i++) {
str.append(cur.e + "->");
cur = cur.next;
}
str.append(cur.e);
str.append("]");
return str.toString();
}
}
@Test public void test_yueshefu() { YueshefuLinked<Integer> linked = new YueshefuLinked(); for (int i = 41; i > 0; i--) { linked.addFirst(i); } System.out.println("循環49次以後:" + linked); linked.checkYueshefu(); //YueshefuLinked: size = 2, [31->16->31]
}