约瑟夫问题

这是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;

}

}

2.

class Circle {

private ArrayList circle = new ArrayList();

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++;

}

}

// 将扔的人设为 true

Person 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 circle = new LinkedList();

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 返回的是删除的 Person

Person 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 testList = new LinkedList();

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_约瑟夫问题 java 实现详解相关推荐

  1. 邀请码 java_邀请码生成器Java代码详解

    邀请码生成器,可根据邀请码反向算出用户id import java.util.Random; /** * 邀请码生成器,算法原理: * 1) 获取id: 1127738 * 2) 使用自定义进制转为: ...

  2. Apache Thrift - java开发详解

    2019独角兽企业重金招聘Python工程师标准>>> Apache Thrift - java开发详解 博客分类: java 架构 中间件 1.添加依赖 jar <depen ...

  3. Java泛型详解-史上讲解最详细的,没有之一

    目录 1. 概述 2. 一个栗子 3. 特性 4. 泛型的使用 4.1 泛型类 4.2 泛型接口 4.3 泛型通配符 4.4 泛型方法 4.4.1 泛型方法的基本用法 4.4.2 类中的泛型方法 4. ...

  4. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  5. java 泛型详解、Java中的泛型方法、 java泛型详解

    本文参考java 泛型详解.Java中的泛型方法. java泛型详解 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即& ...

  6. 最详细的java泛型详解

    来源:最详细的java泛型详解 对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. ja ...

  7. Java异常详解及如何处理

    来源:Java异常详解及如何处理 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言 ...

  8. Java基础——Java NIO详解(一)

    一.基本概念 1.I/0简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通过str ...

  9. Java基础——Java NIO详解(二)

    一.简介 在我的上一篇文章Java NIO详解(一)中介绍了关于标准输入输出NIO相关知识, 本篇将重点介绍基于网络编程NIO(异步IO). 二.异步IO 异步 I/O 是一种没有阻塞地读写数据的方法 ...

  10. Java基础——Java IO详解

    一.概述 1.Java IO Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要 ...

最新文章

  1. java基础编程题(1)
  2. PlantCom:基于内参的宿主相关丰度定量分析揭示植物根系微生物组的微生物总量变化
  3. Hibernate中自动生成数据库表的两种方式
  4. wpf(c#)中获取ComboBox选项值
  5. 机器学习 -- 信息论
  6. .net大型分布式电子商务架构说明(转载来自头条)
  7. 关于ddx/ddy重建法线在edge边沿上的artifacts问题
  8. 二维数组传入函数_C++二维动态数组memset()函数初始化
  9. 新斗罗大陆游戏怎么找回服务器,新斗罗大陆宗门战怎么打 新斗罗大陆手游宗门战打法技巧...
  10. 2022-2027年中国暖气片行业市场全景评估及发展战略规划报告
  11. win10iot c语言,Win10 IoT系统是什么版本?
  12. linux socket cups,Linux打印系统CUPS原理分析
  13. 一封谷歌账号辅助邮箱变更的广告邮件
  14. 【机器视觉】Halcon 19安装教程详解
  15. uni-app 中文档阅读倒计时
  16. Python爬虫知网
  17. 奇迹MU虚拟机 游戏多开无法登陆和登录错误的问题如何解决?
  18. Javascript 新历转旧历|阳历转阴历|公历转农历算法代码
  19. 防火墙虚拟化技术详解(上)
  20. avue框架的Scoped Slot自定义汇总

热门文章

  1. ubuntu-创建桌面快捷方式
  2. DepthMap(1):D. Eigen (NIPS2014)
  3. JAVA 逆向工程技术研究日志
  4. windows11虚拟机安装失败解决办法
  5. 水晶报表 php,VS2015环境下Crystal Reports(水晶报表)的安装使用
  6. 工业机器人实训耗材_工业机器人实训课程
  7. ie浏览器文档模式设置
  8. CommonAPI编写代码
  9. svn 服务器端密码修改,svn服务器端设置密码
  10. 两台计算机共享鼠标,总算发现什么是双模键盘(两台电脑共用一套鼠标键盘)