zoukankan      html  css  js  c++  java
  • 【数据结构与算法】3.3 约瑟夫问题思路、代码实现

    1、约瑟夫问题

    2、代码实现

    package com.hblg.guigu.linklist;
    
    /**
     * @author i
     * @create 2019/9/20 16:39
     * @Description  约瑟夫问题
     *      约瑟夫问题分析:针对于此类问题,我们可以通过创建一个单项环形列表来进行解决。
     *
     *
     */
    public class Josephu {
    
        public static void main(String[] args) {
            CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
            circleSingleLinkedList.addBoyNode(5);
    //        circleSingleLinkedList.showBoy();
            circleSingleLinkedList.countBoy(1,2,5);
        }
    
    }
    
    //创建一个环形单向链表
    class CircleSingleLinkedList{
    
        private Boy first = new Boy(0);//创建一个初始节点
    
    
    
        /***
         * 添加固定节点的思路
         *      思路:nodeNum 表示链表创建的节点数,如果节点数不是一个正常值 直接返回。否则继续
         *      通过for循环 创建需要的节点个数、(这里需要注意的是 在每次生成一个节点的时候 都要将每次新的节点和first节点相关联起来)
         *      如果当前是第一个节点,就将新创建的节点first = boy.  first.setNext(first); 当前节点相关联起来、
         *      否则 每次新创建一个节点boy 通过当前所指向的节点 currentBoy.setNext(boy)  boy.setNext(first) 相关联起来
         *      依次循环 currentNode = boy;
         *
         * @param nodeNum 创建的节点数
         */
        public void addBoyNode(Integer nodeNum){
            if(nodeNum<1){
                System.out.println("创建节点数不正确!");
                return;
            }
            Boy currentBoy = null;
            //创建链表个数
            for (int i = 1; i <= nodeNum; i++) {
                Boy boy = new Boy(i);
                if(i == 1){//创建第一个节点
                    first = boy;
                    first.setNext(first);//节点关联起来
                    currentBoy = first;//将当前的节点和currentBoy节点管理起来
                }else {
                    currentBoy.setNext(boy);
                    boy.setNext(first);
                    currentBoy = boy;
                }
            }
        }
    
        /****
         * 遍历思路:
         *      1.首先先判断空链表的情况 不是的话 继续
         *      2.设置一个当前节点 currentBoy first直接复制给它、
         *      3.通过while循环遍历 当当前节点的下一个节点是first 时候,表名遍历结束 跳出循环
         *        否则的话 将当前节点赋值给下一个节点 currentBoy = currentBoy.next();
         */
        public void showBoy(){
            if(first.getNext() == null){
                System.out.println("链表为空!");
                return;
            }
            Boy currentBoy = first;
            while (true){
                System.out.println("小孩的编号:"+currentBoy.getNo());
                if(currentBoy.getNext() == first){
                    break;
                }
                currentBoy = currentBoy.getNext();
            }
    
        }
    
    
        /***
         * 需求:根据用户的输入,计算出小孩出圈的顺序
         *
         *      实现思路:首先我们应该先判断出参数是否属于正常范围。其次,如果要删除2号节点,那么就需要设置一个标记来指向当前要删除
         *      节点的前一个节点。然后,就是如果当前是从3号节点开始数数 那么我们需要将当前标记节点和指向的节点 遍历到对应的3号节点
         *      最后 通过遍历 如果当前节点和first节点相同,那么就剔除了其他 剩余一个节点。
         *
         * @param startNo   从几号开始  必须从2号开始数数
         * @param countNum  要数的数是多少  2号开始 数 5个数
         * @param countBoys  当前这个圈中有多少人 当前的圈数总人数 比如10人
         */
        public void countBoy(Integer startNo,Integer countNum,Integer countBoys){
            //判断不符合这些条件
            if(first.getNo() == null || startNo<1 || startNo >countBoys){
                System.out.println("当前输入的数据有误");
                return;
            }
            //设置一个标记 用来指示要删除的节点的 前一个节点
            Boy flagBoyNode = first;
            while(true){
                if(flagBoyNode.getNext() == first){
                    break;
                }
                flagBoyNode = flagBoyNode.getNext();
            }
            //如果当前是从3号节点开始数数 那么我们需要将当前标记节点和指向的节点 遍历到对应的3号节点
            for (int i = 0; i < startNo-1 ; i++) {
                first = first.getNext();
                flagBoyNode = flagBoyNode.getNext();
            }
            //最后依次剔除掉每个节点 剩余最后一个节点
            while (true){
                //遍历到初始节点 代表结束
                if(flagBoyNode == first){
                    break;
                }
                //
                for (int i = 0; i < countNum-1; i++) {
                    first = first.getNext();
                    flagBoyNode = flagBoyNode.getNext();
                }
                System.out.println("小孩出圈:"+first.getNo());
    
                //要剔除的节点 将该节点的前后节点关联
                first = first.getNext();
                flagBoyNode.setNext(first);
            }
                System.out.println("剩余孩子:"+first.getNo());
        }
    
    }
    
    /***
     * Boy节点:一个no next节点
     */
    class Boy{
        private Integer no;//id编号
        private Boy next;//指向下一个节点
    
        public Boy(Integer no) {
            this.no = no;
        }
    
        public Integer getNo() {
            return no;
        }
    
        public void setNo(Integer no) {
            this.no = no;
        }
    
        public Boy getNext() {
            return next;
        }
    
        public void setNext(Boy next) {
            this.next = next;
        }
    
        @Override
        public String toString() {
            return "Boy{" +
                    "no=" + no +
                    ", next=" + next +
                    '}';
        }
    }
  • 相关阅读:
    url
    松弛时间
    Linux下为当前用户添加 PYTHONPATH 环境变量
    ElasticSearch集群的安装(windows)
    软件开发安全
    java,判断手机设备跟adb建立连接
    question
    氚云后台代码小栗子,流程表单新增完成反写源单状态
    November Challenge 2020 Division 1
    February Challenge 2021 Division 1 选做
  • 原文地址:https://www.cnblogs.com/qxlxi/p/12860812.html
Copyright © 2011-2022 走看看