循環單鏈表解決約瑟夫問題
package cn.agan.link;
/**
* 約瑟夫問題:
* 據說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39 個猶太人與Josephus及他的朋友躲到一個洞中,
* 39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,
* 然後再由下一個重新報數,直到所有人都自殺身亡爲止。然而Josephus 和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因爲第一個人已經被越過),
* 並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。
* 問題是,給定了和,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,
* 於是逃過了這場死亡遊戲
* 簡言之: N個人圍成一圈,從第一個開始報數,第M個將被殺掉,最後剩下一個,其餘人都將被殺掉。例如N=6,M=5,被殺掉的順序是:5,4,6,2,3,1。
*/
public class JosephuCircularLink {
public static void main(String[] args) {
SingleLinkList l = new SingleLinkList();
l.fullPersion(6);
l.show();
l.killCircular(2);
}
}
//單向環形鏈表
class SingleLinkList {
private Person first;
public void add(Person p) {
if (first == null) {
first = p;
p.setNext(p);
return;
}
Person tmp = first.getNext();
while (tmp.getNext() != first) {
tmp = tmp.getNext();
}
p.setNext(tmp.getNext());
tmp.setNext(p);
}
//約瑟夫殺人
public void killCircular(int M) {
if (first == null || M < 1 ) {
System.out.println("沒有人可以被殺害");
return ;
}
Person prevP = first.getNext();
while (prevP.getNext() != first) {
prevP = prevP.getNext();
}
while (true) {
if (prevP == first) {
break;
}
for (int i = 1; i < M; i++) {
prevP = prevP.getNext();
first = first.getNext();
}
System.out.println(first.getNo()+"被殺");
prevP.setNext(first.getNext());
first = prevP.getNext();
}
System.out.println("最後存活的是"+first.getNo());
}
public void fullPersion(int num) {
if (num < 1) {
System.out.println("參數有誤");
return;
}
for (int i = 0; i < num; i++) {
Person p = new Person(i+1, "我是"+(i+1));
add(p);
}
}
public void show() {
System.out.println(first+"\t");
Person p = first.getNext();
while (p != first) {
System.out.println(p+"\t");
p = p.getNext();
}
}
}
//人
class Person {
private int no;
private String name;
private Person next;
public Person(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person getNext() {
return next;
}
public void setNext(Person next) {
this.next = next;
}
@Override
public String toString() {
return "Person{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}