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

    题目描述

    据说著名犹太历史学家 Josephus 有过以下故事:在罗马人占领乔塔帕特后,39 个犹太人与 Josephus 及他的朋友躲到一个洞中,39 个犹太人决定宁愿死也不要被敌人抓到,于是决定了一种自杀方式,41 个人排成一个圆圈,由第 1 个人开始报数,报数到 3 的人就自杀,然后再由下一个人重新报 1,报数到 3 的人再自杀,这样依次下去,直到剩下最后一个人时,那个人可以自由选择自己的命运。这就是著名的约瑟夫问题。现在请用单向环形链表得出最终存活的人的编号。

    题目分析:

    本例可以使用链表(包括单向循环链表或者双向循环链表),数组来完成,具体可以根据自己需求或者熟悉哪一种。个人感觉循环链表更加形象,易于理解和操作。

    代码实现:

    package 链表;
    
    public class Main {
        public static void main(String[] args){
            JosePhus josePhus = new JosePhus();
            josePhus.getResult(39,3);
        }
    }
    
    class InfoNode{
        public int id;
        public InfoNode next;
    
        public InfoNode(int id){
            this.id = id;
        }
    
        @Override
        public String toString() {
            return "InfoNode[" +
                    "id=" + id +
                    ']';
        }
    }
    
    class JosePhus{
    
        public InfoNode start = null;
        private void addBoyNum(int n) {
            System.out.println("链表数据校验......");
            if (n < 1 ){
                System.out.println("n必须大于等于1");
                return;
            }
            System.out.println("正在创建链表......");
    
            InfoNode temp = null; //用于控制后续的添加操作
            for (int i = 1; i <= n ; i++) {
                InfoNode infoNode = new InfoNode(i);
                if (i == 1){
                    start = infoNode; //给第一个节点赋值
                    start.next = start;//指向自己
                    temp = start; //给temp赋值以后 后续的增加节点操作就用它代替
    
                }else {
                    temp.next = infoNode;
                    temp = temp.next;//然后temp后移
                    temp.next = start;//后移完成以后 再指向头部
                }
            }
            System.out.println("环形链表创建完成~~~~");
    
        }
    
       public void getResult(int n, int m){
           //1.先调用方法创建一个有n节点的环形链表
           addBoyNum(n);
    
           //2.校验数据是否正确
           if (m > n  || m > 1000 || m < 1){
               System.out.println("输入的n或m不符合要求~~~~");
               return;
           }
    
           InfoNode temp = start;
           //3.出圈的时候要让temp始终位于start之前,所以接下来要让他先跑到最后一个位置
           while (true){
               if (temp.next == start){
                   break;
               }
               temp = temp.next;
           }
           //4.temp走到指定位置 开始出圈
           while (true){
               if (temp == start){
                   System.out.println("遍历结束!");
                   break;
               }
    
               for (int i = 1; i <= m-1  ; i++) {
                    start = start.next;
                    temp = temp.next;
               }
               System.out.println("出圈节点编号:"+start.id);
               //去除出圈的节点
               start = start.next;
               temp.next = start;
           }
           //当退出整个循环以后 说明只剩一个节点,就是幸存的人
           System.out.println("幸存者id是:"+start.id);
       }
    }
    
    

    最后:

    LeetCode自带的编译器结果不让过,但是idea里是没问题的,很懵......不知道这个是什么情况,还没玩懂怎么操作~~~~~蓝瘦
  • 相关阅读:
    spring-boot整合freemarker 出现404
    java rmi的基本使用
    spring的Autowired、Resource、Inject的使用
    RabbitMQ topic 交换器
    RabbitMQ direct交换器
    RabbitMQ java 原生代码
    RabbitMQ基本概念
    消息中间件
    设计模式——模板模式
    设计模式——代理模式
  • 原文地址:https://www.cnblogs.com/coding-996/p/12263407.html
Copyright © 2011-2022 走看看