约瑟夫问题

这是17世纪的法国数学家加斯帕在《数目的游戏问题》中讲的一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,数到第九个人就将他扔入大海。该人后面的人从1开始重新报数,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。

思路
1. 先建立一个类,有 id 和 isRemove

class Person {int id;boolean isRemove;public Person(int id, boolean isRemove) {this.id = id;this.isRemove = isRemove;}public boolean isRemove() {return isRemove;}public void setRemove(boolean isRemove) {this.isRemove = isRemove;}
}
  1. 2.
class Circle {private ArrayList<Person> circle = new ArrayList<Person>();private int amount; // 一共多少人Circle(int amount) {this.amount = amount;for (int i = 0; i < amount; i++) {Person p = new Person(i + 1, false);circle.add(p);}}/*** * @param index*            最开始扔人的位置,比如第9人* @param total*            共需要扔几次*/public void getIndex(int index, int total) {// 起始位置int currentIndex = -1;for (int t = 0; t < total; t++) {int notRemove = 0;//本来是notRemove != 9,写死不好while (notRemove != index) {currentIndex++;// 或者用 currentIndex % amount 解决if (currentIndex == amount) {currentIndex = 0;}if (!circle.get(currentIndex).isRemove) {notRemove++;}}// 将扔的人设为 truePerson p = circle.get(currentIndex);p.setRemove(true);circle.set(currentIndex, p);System.out.printf("第 %-2d 次仍的人id是%4d\n", t + 1, p.id);}}}

代码建立一个容器来保存各个人,主要就是不移除这个人,而是把他状态设为setRemove(true),好处这样容器的大小保持不变。如果删掉这样人,容器大小每次减1,算起来麻烦


if (currentIndex == amount) {currentIndex = 0;
}

本来是用 currentIndex % amount 实现的,不过本代码都是+1,肯定会有 == amount的情况,用置为0更好

结果

第 1  次仍的人id是   9
第 2  次仍的人id是  18
第 3  次仍的人id是  27
第 4  次仍的人id是   6
第 5  次仍的人id是  16
第 6  次仍的人id是  26
第 7  次仍的人id是   7
第 8  次仍的人id是  19
第 9  次仍的人id是  30
第 10 次仍的人id是  12
第 11 次仍的人id是  24
第 12 次仍的人id是   8
第 13 次仍的人id是  22
第 14 次仍的人id是   5
第 15 次仍的人id是  23

优化

也可以用数组实现,下标和 boolean 正好模拟上面的 Person 类

static void other() {boolean[] usaJapa = new boolean[30];// 用类库初始化Arrays.fill(usaJapa, true);int leftCount = usaJapa.length;int countNum = 0;int index = 0;int i = 0;while (leftCount > 15) {if (usaJapa[index]) {countNum++;}if (countNum == 9) {countNum = 0;usaJapa[index] = false;leftCount--;System.out.printf("第 %-2d 次仍的人id是%4d\n", ++i, index + 1);}index++;if (index == usaJapa.length) {index = 0;}}}

用链表实现,remove 其中的数据

class Circle {private LinkedList<Person> circle = new LinkedList<Person>();private int amount; // 一共多少人Circle(int amount) {this.amount = amount;for (int i = 0; i < amount; i++) {Person p = new Person(i + 1, false);circle.add(p);}}public void othergetIndex(int mark, int total) {// remain 是剩下的人数,total 是需要删除的人数int remain = amount;int count = 0;int current = 0;int i = 0;while (remain > amount - total) {count++;// 注意这人如果达到 mark,比如第9个人// 删掉第9个人后,再删第9个人,就是删原来的第10个人if (count == mark) {// remove 返回的是删除的 PersonPerson p = circle.remove(current);System.out.printf("第 %-2d 次仍的人id是%4d\n", ++i, p.id);count = 0;remain--;} else {current++;}if (current == amount - i) {current = 0;}}}
}

用 LinkedList 删除操作更快,

Person p = circle.remove(current);
remove 返回删除的元素

LinkedList<Integer> testList = new LinkedList<Integer>();
for (int i = 0; i < 10; i++) {testList.add(i);
}
for (int i = 0; i < 5; i++) {System.out.println(testList.remove(3));
}   /***   3*   4*   5*   6*   7*/

这段代码的输出可以看出,删除了第3个元素,后面元素往前移动

约瑟夫问题 java 实现相关推荐

  1. 【每日一题】洛谷--P1996 约瑟夫问题 java题解

    文章目录 题目链接 题解 题目链接 洛谷–P1996约瑟夫问题 题解 约瑟夫问题细品一下,就是一个链表成环,根据规则要求逐渐remove的一个思路.代码详解如下: package com.compan ...

  2. 约瑟夫问题JAVA算法

    去年学院举办的算法设计比赛,当时使用的c语言来描述的,而且当时刚刚学了数据结构.于是就用到循环链表来解决,虽然答案没有完全出来,但是评分的老师,看了我的代码和思路,也许是半个感情分,毕竟是学校的算法比 ...

  3. 约瑟夫环 java代码_约瑟夫环算法的Java实现代码

    相信大家都知道这是一个的算法问题,约瑟夫环的c语言实现是利用了指针链表的形式,java实现呢,我的这个是用了内部类. 算法描述:n个人围成一圈,每人有一个各不相同的编号,选择一个人作为起点,然后顺时针 ...

  4. 约瑟夫环 java实现

    曾经一次笔试,由于准备不足,前面所有题都打完了,但是最后一题,就是手写约瑟夫环,我居然没有写出来,然后..凉凉了.. 现在再来回顾一下: 问题:有100个人围成一个圈,从1开始报数,报到14的这个人就 ...

  5. 约瑟夫问题java 递归_从约瑟夫问题的递归实现的问题说起

    在解决约瑟夫问题时,我比较推荐使用递归,因为递归实现的算法代码更短,逻辑也更清晰,然而很多人有一个疑问,那就是他们知道递归层数是有极限的,这就意味着当需要很大层数的递归时,递归算法是不可行的,会导致段 ...

  6. 约瑟夫问题java代码

    public class Josephus {public static void main(String[] args) {//总人数为41int total = 41;MyNode first = ...

  7. POJ-2746:约瑟夫问题(Java版)

    问题描述: 题目要求,这里就不再给出了.大致描述如下:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数.就这样, ...

  8. 约瑟夫问题(丢手帕问题)的java实现

    约瑟夫问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉.例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3.最后剩下1号.借用一些自己感兴趣的球星的名字,使 ...

  9. java模拟单链表环形链表解决约瑟夫问题

    java模拟环形链表解决约瑟夫问题 此文是观看尚硅谷韩老师的数据结构与算法学习视频整理的笔记 约瑟夫问题描述 约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算 ...

最新文章

  1. Docker运行sonarqube-(代码质量检测平台)
  2. 欧拉函数 cojs 2181. 打表
  3. 使用Spark Shell开发运行Spark程序
  4. 校企合作与集成电路--华为在行动
  5. C# datagridview 实现按指定某列或多列进行排序
  6. web文件被更改crawlergo怎么解决_hscan:一款集成crawlergo和xray的src漏洞挖掘利器
  7. 涵盖农业、可再生能源、酒店、金融服务、创意服务、科技、林业和建筑业的20家新公司加入《气候宣言》
  8. 基于matlab的简易诊断系统,基于matlab的图像识别
  9. 定时任务cron表达式工具
  10. c++使用librdkafka kerberos认证
  11. FC经典游戏600合集for mac(小霸王游戏) 中文版
  12. 我的眼眸,等你路过我的容颜
  13. Java中抽象类和接口的区别
  14. Impala 4.0 启用 LZO
  15. Windows/Linux混合刻录之后,光盘文件不见了?
  16. IP数据包在网络中的传输过程
  17. 【IPFS应用开发】ipfs安卓节点编译 ipfs andriod node
  18. 博德之门 linux x32,GOG.com
  19. 高斯-克吕格(Gauss-Kruger)投影与UTM投影的在ArcGIS中的区别
  20. 有机晶体数据库_ChIN简介页:剑桥晶体结构数据库(CSD, 有机、金属有机物)

热门文章

  1. P1983 车站分级(拓扑排序)
  2. 高德地图 python面试_【高德地图面试|面试题】-看准网
  3. L/O(输出/输入)
  4. Linux系统编程手册-源码的使用
  5. nyoj 118 修路方案【次小生成树】
  6. 环保建设和环保理念_环保网站设计展示
  7. React全家桶包含哪些
  8. 源码分析 | Mybatis接口没有实现类为什么可以执行增删改查
  9. 关于人生的一些哲理和名句
  10. progressive-generation-master代码记录【下载处理数据】(定义CNNDataset类)