zoukankan      html  css  js  c++  java
  • 约瑟夫问题

    问题来历

    据说著名犹太历史学家 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也不会死!

  • 相关阅读:
    Android 数据库框架OrmLite的使用(二)
    Fragment响应返回键
    jQuery判断当前元素显示状态并控制元素的显示与隐藏
    Android UI设计中一些不错的示例及第三方控件
    js数组操作总结
    Easyui datagrid 设置内容超过单元格宽度时自动换行显示
    Easyui datagrid 扩展单元格textarea editor
    Easyui datagrid combobox输入框非法输入判断与事件总结
    Tomcat 参数配置相关
    单元测试_JUnit常用单元测试注解介绍及代码演示
  • 原文地址:https://www.cnblogs.com/zby9527/p/10980833.html
Copyright © 2011-2022 走看看