约瑟夫环问题详解(java版)
1 什么是约瑟夫环问题?
约瑟夫,是一个古犹太人,曾经在一次罗马叛乱中担任将军,后来战败,他和朋友及另外39个人躲在一口井里,但还是被发现了。罗马人表示只要投降就不死,约瑟夫想投降,可是其他人坚决不同意。怎么办呢,他想到一个主意:
让41个人围成一个圆圈,从第一个人开始报数,数到3的那个人被旁边的人杀死。这样就可以避免自杀了,因为犹太人的信仰是禁止自杀的。结果一群人杀来杀去最后只剩下两个了,就是约瑟夫和他朋友,于是两人愉快地去投降了。
约瑟夫和朋友站在什么位置才保住了性命呢,这就是我们今天要讲的约瑟夫环问题。
2 问题的重要性
这是个BAT常用面试题,而且本质上是一个游戏,可以广泛应用于生活中,工作生活好帮手就是它了。
3 约瑟夫环抽象问题
这个问题实际在讲:N个人围成一圈,第一个人从1开始报数,报M的被杀掉,下一个人接着从1开始报,循环反复,直到剩下最后一个,那最后胜利者的初始位置在哪里?
模拟流程:
假如有5个人报数,报到3被杀,情况如下
A B C1 D E (初始位置,C第一个被杀)
D E A2 B (C死后的第二次排位,A第二个被杀)
B D E3 (A死后的第三次排位,E第三个被杀)
B4 D (E死后的第四次排位,B第四个被杀)
D (D留在了最后,初始位置是4)
解决方法:
1 循环遍历法
public static int josephus(int n, int m) {
//n个人, 0 1 2..n-1
int[] people = new int[n];
//人的索引
int index = -1;
//报数记录, 1 2 3..m
int count = 0;
//剩余人数 初始值为n
int remain = n;//为了找到最后一个幸存者的位置,假设所有人都会被杀
while (remain > 0) {
index++; //找到报数的人
if (index == n) { //所有人遍历一圈后从头遍历
index = 0;
}
if (people[index] == -1) { //如果当前的人被杀 跳过
continue;
}count++; //报数
if (count == m) {
people[index] = -1; //报数到m后杀人
count = 0; //报数重置
remain--; //剩余人数递减
}
}
return index;
}
将41传入方法后,可得结果为30, 因为是从0开始计数,所以等价于现实世界的第31位。
如果约瑟夫也用这种常规方式去解决问题,那么就无法快速计算出自己应该站的位置了,所以一定有更简方法,那就是"递归法"。
2 递归法
模拟流程(第一种情况和上边表述相同):
假如有5个人报数,报到3被杀,情况如下
0 1 2 3 4 (假设从0开始计算位置)
A B C1 D E (初始位置,C第一个被杀)
D E A2 B (C死后的第二次排位,A第二个被杀)
B D E3 (A死后的第三次排位,E第三个被杀)
B4 D (E死后的第四次排位,B第四个被杀)
D (D留在了最后,初始位置是3)
假如有4个人报数,报到3被杀,情况如下
0 1 2 3
A B C1 D(初始位置,C第一个被杀)
D A B2 (C死后的第二次排位,B第二个被杀)
D3 A (B死后的第三次排位,D第三个被杀)
A (D留在了最后,初始位置是0)
可以看到,n个人报数,死掉一个人后,变成了n-1个人报数的问题,和n-1个人直接报数的区别只在于下角标。那我们来看一下下角标使怎么变化的?我们把重新排位前的位置叫old,新的位置叫new, 则情况如下:
old new
D 3 -> 0
A 0 -> 1
B 1 -> 2
old = (new + 3)%4 -- 为了不超过n本身 对n取模
old等价于f(n,m), n个人报数m的情况, 而new等价于f(n-1,m),即为n-1个人报数m的情况。
则最终公式为 f(n,m) = (f(n-1,m) + m)%n
递归:是把复杂问题递推为最简问题,然后将结果回归的过程。
步骤:找规律 & 找出口
则编写代码如下。
public static int josephusByRec(int n, int m) {
if (n == 1) { //出口
return 0;
}
return (josephusByRec(n - 1, m) + m) % n;
}
4 总结
这是发生在公元66到67年间的故事,是一个来自2000年前古人的智慧,追古思今,你学会了吗?
———来自若愚小姐的算法课
约瑟夫环问题详解(java版)的更多相关文章
- 约瑟夫环问题详解 (c++)
问题描述: 已知n个人(以编号0,2,3...n-1分别表示)围坐在一起.从编号为0的人开始报数,数到k的那个人出列:他的下一个人又从1开始报数,数到k的那个人又出列:依此规律重复下去,直到圆桌周围的 ...
- 超全详解Java开发环境搭建
摘自:https://www.cnblogs.com/wangjiming/p/11278577.html 超全详解Java开发环境搭建 在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必 ...
- 「跬步千里」详解 Java 内存模型与原子性、可见性、有序性
文题 "跬步千里" 主要是为了凸显这篇文章的基础性与重要性(狗头),并发编程这块的知识也确实主要围绕着 JMM 和三大性质来展开. 全文脉络如下: 1)为什么要学习并发编程? 2) ...
- 详解Java GC的工作原理+Minor GC、FullGC
详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...
- Protocol Buffer技术详解(Java实例)
Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发 ...
- 详解Java中的clone方法
详解Java中的clone方法 参考:http://blog.csdn.net/zhangjg_blog/article/details/18369201/ 所谓的复制对象,首先要分配一个和源对象同样 ...
- java基础(十五)----- Java 最全异常详解 ——Java高级开发必须懂的
本文将详解java中的异常和异常处理机制 异常简介 什么是异常? 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常. Java异常的分类和类结构图 1.Java中的所 ...
- 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)
在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...
- 第三节:带你详解Java的操作符,控制流程以及数组
前言 大家好,给大家带来带你详解Java的操作符,控制流程以及数组的概述,希望你们喜欢 操作符 算数操作符 一般的 +,-,*,/,还有两个自增 自减 ,以及一个取模 % 操作符. 这里的操作算法,一 ...
随机推荐
- js 正则表达式:价格的校验
/*验证单价:包括两位小数*/var priceReg = /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/;var price=$("#price& ...
- java 手机号码+邮箱的验证
import java.util.regex.Pattern; //导入的包 1:String REGEX_MOBILE = "^((17[0-9])|(14[0-9])|(13[0-9]) ...
- FJUT - OJ优先队列专题题解
题目链接http://120.78.128.11/Contest.jsp?cid=18 题面不贴了 都是英文题,看的我心力憔悴 =7= 一.Ugly Numbers 题目说一个数的质因数只包含2.3或 ...
- python语言程序设计部分习题
第二章 python程序实例解析 程序练习题 2.1 实例1的修改,采用eval(input(<提示内容>))替换现有输入部分,并使输出的温度值为整数. vv 2.2 汇率兑换程序.按 ...
- [C++]类的设计(2)——拷贝控制(阻止拷贝)
1.阻止拷贝的原因:对于某些类来说,拷贝构造函数和拷贝赋值运算符没有意义.举例:iostream类阻止了拷贝,以避免多个对象写入或者读取相同的IO缓冲. 2.阻止拷贝的方法有两个:新标准中可以将成 ...
- Java职责链模式
一.定义 职责链模式,就是将能够处理某类请求事件的一些处理类,类似链条的串联起来.请求在链条上处理的时候,并不知道具体是哪个处理类进行处理的.一定程度上实现了请求和处理的解耦. 实际生活中的经典例子就 ...
- 『嗨威说』算法设计与分析 - STL中Sort函数的实现原理初探
本文索引目录: 一.对Sort算法实现的个人阅读体会 二.Sort算法使用的三个排序算法的优点介绍 2.1 插入排序的优缺点 2.2 堆排序的优缺点 2.3 快速排序的优缺点 2.4 新的结合排序—— ...
- MySQL在Linux系统环境的安装和无主机登录配置
将mysql 安装在单个Linux系统主机,并配置本地或远程(此处可仅单指局域状态下的环境)的无主机登录.谨记的是:操作完mysql 设置时,需以flush privileges进行权限 ...
- Scrapy项目 - 数据简析 - 实现斗鱼直播网站信息爬取的爬虫设计
一.数据分析截图(weka数据分析截图 2-3个图,作业文字描述) 本次将所爬取的数据信息,如:房间数,直播类别和人气,导入Weka 3.7工具进行数据分析.有关本次的数据分析详情详见下图所示: ...
- java+maven+jenkins+svn构建
操作参照:https://blog.csdn.net/qq_34977342/article/details/82346915 1.创建一个自由风格的项目,起名字 2.设置构建项目最大保存数量,与天数 ...