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

    概念介绍

      有同学想了解约瑟夫问题,今天它来了!直接进入主题,什么是约瑟夫问题?约瑟夫问题:N个人围成一圈,从约定编号为K的人开始报数,第M个将被杀掉,依次类推,最后剩下一个,其余人都将被杀掉

      直接上图展示,初始化状态: 假设n=6,总共有6个人,k=1,从第一个人开始报数,m=5,每次数五个

      

          第一次报数:从一号开始,数五个数,1-2-3-4-5,数完五个数,五号被杀死,第一次报数后,剩余人数如下

      

      第二次报数: 从被杀死的五号的下一位开始报数,也就是六号,数五个数,6-1-2-3-4,数数完毕,四号被杀死,第二次报数后,剩余人数如下

      

      第三次报数: 从被杀死的四号的下一位开始报数,同样是六号,数五个数,6-1-2-3-6,数数完毕,六号被杀死,第三次报数后,剩余人数如下

      

      第四次报数: 从被杀死的六号的下一位开始报数,也就是一号,数五个数,1-2-3-1-2,数数完毕,二号被杀死,第四次报数后,剩余人数如下

      

      第五次报数: 从被杀死的二号的下一位开始报数,也就是三号,数五个数,3-1-3-1-3,数数完毕,三号被杀死,只剩下一号,Game Over!

      

     代码实现

      实现思路:用单向循环链表来表示圈,将人杀死后修改链表上的节点即可。

      第一步:构建节点上对象。

     1 class Person {
     2     // 人的编号
     3     private int no;
     4     // 指向下一个人
     5     private Person next;
     6 
     7     public Person(int no) {
     8         this.no = no;
     9     }
    10 
    11     public int getNo() {
    12         return no;
    13     }
    14 
    15     public void setNo(int no) {
    16         this.no = no;
    17     }
    18 
    19     public Person getNext() {
    20         return next;
    21     }
    22 
    23     public void setNext(Person next) {
    24         this.next = next;
    25     }
    26 
    27 }

      第二步:创建一个环形的单向链表,将带有编号的人组织起来。

    class CircleSingleLinkedList {
        // 创建一个first节点,当前没有编号
        private Person first = null;
    
        // 往环形链表中添加人,persons表示添加的人数
        public void addPerson(int persons) {
            if (persons < 1) {
                System.out.println("persons的值异常");
                return;
            }
            // 辅助指针,帮助构建环形链表
            Person curPerson = null;
            // 往环形链表中添加人
            for (int i = 1; i <= persons; i++) {
                Person person = new Person(i);
                // 如果是第一次添加人
                if (i == 1) {
                    first = person;
                    first.setNext(first);
                    curPerson = first;
                } else {
                    curPerson.setNext(person);
                    person.setNext(first);
                    curPerson = person;
                }
            }
        }
    }

      第三步:实现数数的方法。

        /**
         *
         * @param startNo
         *            表示从第几个人开始数数
         * @param countNum
         *            表示每次数几下
         * @param nums
         *            表示圈中的人数
         */
        public void startCount(int startNo, int countNum, int nums) {
            if (first == null || startNo < 1 || startNo > nums) {
                System.out.println("参数输入有误, 请重新输入");
                return;
            }
            // 辅助指针,当我们要退出时的依据,当helper == first时,退出
            Person helper = first;
            // 需求创建一个辅助指针(变量) helper , 事先应该指向环形链表的最后这个节点
            while (true) {
                if (helper.getNext() == first) {
                    break;
                }
                helper = helper.getNext();
            }
            // 报数开始前,先让first和helper移动 k - 1次
            for(int j = 0; j < startNo - 1; j++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            // 报数开始时,让first和helper指针同时 的移动 m  - 1 次, 然后first指向人被杀死,出圈
            // 这里是一个循环操作,直至圈中只有一个节点
            while(true) {
                // 当helper == first时,说明圈中只有一个节点
                if(helper == first) {
                    break;
                }
                // 让 first 和 helper 指针同时移动 countNum - 1
                for(int j = 0; j < countNum - 1; j++) {
                    first = first.getNext();
                    helper = helper.getNext();
                }
                System.out.printf("第%d号人被杀死
    ", first.getNo());
                // 出圈操作
                first = first.getNext();
                helper.setNext(first);
    
            }
            System.out.printf("最后留在圈中的人的编号是:%d 
    ", first.getNo());
        }

      至此,代码编写完成,Git地址:https://github.com/HollowCup/algorithms-and-data-structure,具体实现位于algorithms工程下的josephus目录,如果发现不足之处,请联系我进行更改,十分感谢!关注我,为你揭秘更多算法!

  • 相关阅读:
    Docker部署Tomcat实例
    Redis+Sentinel 实现redis集群高可用
    Jenkins+Maven+SVN
    Python的装饰器
    执行hadoop fs -ls时出现错误RuntimeException: core-site.xml not found
    hbase的存储体系
    Sqoop import加载HBase过程中,遇到Permission denied: user=root, access=WRITE, inode="/user":hdfs:supergroup:drwxr-xr-x
    Java操作hbase总结
    Java文件操作 读写操作
    HBase 学习之一 <<HBase使用客户端API动态创建Hbase数据表并在Hbase下导出执行>>
  • 原文地址:https://www.cnblogs.com/maguanyue/p/11568705.html
Copyright © 2011-2022 走看看