约瑟夫问题
問題來歷
據說著名猶太歷史學家 Josephus有過以下的故事:在羅馬人占領喬塔帕特后,39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧愿死也不要被敵人抓到,于是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然后再由下一個重新報數,直到所有人都自殺身亡為止。然而Josephus 和他的朋友并不想遵從。首先從一個人開始,越過k-2個人(因為第一個人已經被越過),并殺掉第k個人。接著,再越過k-1個人,并殺掉第k個人。這個過程沿著圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活著。問題是,給定了和,一開始要站在什么地方才能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,于是逃過了這場死亡游戲。
面向對象還是面向過程?
如果你腦海里都是if-else之類的,或者各種高階公式,那么你可能在使用面向過過程的思維方式,當然如果你數學夠好,可能有很好的解法
如果你想不到直接的解決辦法,不妨嘗試下面向對象的思維方式。
先構造一個環形結構,每個節點代表一個人,然后開始數數,數到第三個就把這個節點從環形結構中移除,最后剩下的就是活下來的,這樣是不是就簡單很多了。
當然,這個環形結構肯定需要有個頭,不然Josephus可能也不知道該站在第幾個位置。
其實實現方式有很多,環形結構用數組和鏈表也都行。
以下是我的實現方式,僅供參考。
代碼實現:
package com.zby;
public class JosephusCircle {
private Node headNode;
public void add(Object data) {
Node newNode = new Node();
newNode.dataObject = data;
if (null == headNode) {
headNode = newNode;
newNode.preNode = newNode;
newNode.nextNode = newNode;
} else {
Node lastNode = headNode.preNode;
lastNode.nextNode = newNode;
newNode.preNode = lastNode;
newNode.nextNode = headNode;
headNode.preNode = newNode;
}
}
public void removeIndexAndReset(int index) {
if (null == headNode) {
System.out.println("請先添加節點");
return;
}
while (headNode.nextNode != headNode) {
Node removeNode = headNode;
for (int i = 1; i < index; i++) {
removeNode = removeNode.nextNode;
}
headNode = removeNode.nextNode;
removeNode.preNode.nextNode = removeNode.nextNode;
removeNode.nextNode.preNode = removeNode.preNode;
System.out.println(removeNode + "自殺");
}
System.out.println(headNode + "存活");
}
private class Node {
private Node preNode;
private Node nextNode;
private Object dataObject;
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Node [dataObject=");
builder.append(dataObject);
builder.append("]");
return builder.toString();
}
}
public static void main(String[] args) {
JosephusCircle josephusCircle = new JosephusCircle();
for (int i = 1; i < 42; i++) {
if (i == 16) {
josephusCircle.add("第" + i + "個是約瑟夫的朋友");
} else if (i == 31) {
josephusCircle.add("第" + i + "個是約瑟夫");
} else {
josephusCircle.add("第" + i + "個是猶太人");
}
}
josephusCircle.removeIndexAndReset(3);
}
}
Node [dataObject=第3個是猶太人]自殺 Node [dataObject=第6個是猶太人]自殺 Node [dataObject=第9個是猶太人]自殺 Node [dataObject=第12個是猶太人]自殺 Node [dataObject=第15個是猶太人]自殺 Node [dataObject=第18個是猶太人]自殺 Node [dataObject=第21個是猶太人]自殺 Node [dataObject=第24個是猶太人]自殺 Node [dataObject=第27個是猶太人]自殺 Node [dataObject=第30個是猶太人]自殺 Node [dataObject=第33個是猶太人]自殺 Node [dataObject=第36個是猶太人]自殺 Node [dataObject=第39個是猶太人]自殺 Node [dataObject=第1個是猶太人]自殺 Node [dataObject=第5個是猶太人]自殺 Node [dataObject=第10個是猶太人]自殺 Node [dataObject=第14個是猶太人]自殺 Node [dataObject=第19個是猶太人]自殺 Node [dataObject=第23個是猶太人]自殺 Node [dataObject=第28個是猶太人]自殺 Node [dataObject=第32個是猶太人]自殺 Node [dataObject=第37個是猶太人]自殺 Node [dataObject=第41個是猶太人]自殺 Node [dataObject=第7個是猶太人]自殺 Node [dataObject=第13個是猶太人]自殺 Node [dataObject=第20個是猶太人]自殺 Node [dataObject=第26個是猶太人]自殺 Node [dataObject=第34個是猶太人]自殺 Node [dataObject=第40個是猶太人]自殺 Node [dataObject=第8個是猶太人]自殺 Node [dataObject=第17個是猶太人]自殺 Node [dataObject=第29個是猶太人]自殺 Node [dataObject=第38個是猶太人]自殺 Node [dataObject=第11個是猶太人]自殺 Node [dataObject=第25個是猶太人]自殺 Node [dataObject=第2個是猶太人]自殺 Node [dataObject=第22個是猶太人]自殺 Node [dataObject=第4個是猶太人]自殺 Node [dataObject=第35個是猶太人]自殺 Node [dataObject=第16個是約瑟夫的朋友]自殺 Node [dataObject=第31個是約瑟夫]存活
當然,我們只留下了最后一個人,第31號位置,說明如果Josephus把自己放在了絕對安全的位置,如果他的朋友想繼續玩,那么Josephus也不會死!
總結
- 上一篇: 做一个有效的管理者
- 下一篇: allure的内容以及用法