问题来历
据说著名犹太历史学家 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也不会死!
最新评论