笔者昨天看电视,偶尔看到一集讲述古罗马人与犹太人的战争——马萨达战争,深为震撼,有兴趣的同学可以移步:http://finance.ifeng.com/a/20170627/15491157_0.shtml .
  这不仅让笔者想起以前在学数据结构时碰到的Josephus问题:
  据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人找到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
  以前我们都是用链表的方法编程来解决这个问题的,这次笔者将会讲述两个不同的方法,一个是笔者自己的朴素想法,一个是数学方法。

  • 朴素方法
  • 数学方法

  首先我们先将Josephus问题描述出来,即: 共有N个人围成一圈,编号分别为1,2,…,N,从第一个人开始从1到m报数,报到m的人退出,如此循环下去,直至最后一个人。问最后一个人的最开始的编号是几?
  先是笔者的朴素想法。
  将N个人储存在列表(list)中,每次报到m的元素剔除,并记录下最后一个人报的数i,然后将缩短后的数组从i+1报数,如此循环下去,直至列表的长度为1,这样剩下来的元素就是我们要求的答案。
  这种想法虽然素朴,比较容易实现,但是时间复杂度为O(Nm).
  接着是数学方法。
  假设一开始的Josephus环编号为0,1,2,…,N-1.我们知道第一个人(编号一定是m%N-1) 出列之后,剩下的N-1个人组成了一个新的Josephus环(以编号为k=m%n的人开始):

k,k+1,k+2,......,n−2,n−1,0,1,2,...k−2k,k+1,k+2,......,n−2,n−1,0,1,2,...k−2

并且从k开始报0.
  现在我们把他们的编号做一下转换:

k−−>0k+1−−>1k+2−−>2...k−2−−>n−2k−1−−>n−1k−−>0k+1−−>1k+2−−>2...k−2−−>n−2k−1−−>n−1

变换后就成为了(N-1)个人报数的子问题,这启示我们可以用归纳法来解决这个问题。假如我们知道这个子问题的解为xx,原来问题的答案为x′x′,则x′=(x+k)%n.x′=(x+k)%n.因此,递推公式就有了!令f(i)f(i)表示ii个人玩游戏报mm退出最后胜利者的编号,我们要求的结果是f(N)f(N),其递推公式如下:

f(1)=0f(i)=(f(i−1)+m)%i(i>1)f(1)=0f(i)=(f(i−1)+m)%i(i>1)

  数学方法简单明了,计算效率高,但是推导比较困难。
  最后,我们给出以下两种方法的Python代码和朴素方法的Java代码,希望能给大家一点思考。
  完整的Python代码如下:

# -*- coding: utf-8 -*-# This code is devoted to solve the Josephus Problem by Python.# N: numper of people
# m: cycle number
def solve1(N, m):a = list(range(1, N+1)) # sequenceend = 0 # the number of last man in sequencewhile len(a) > 1:b = []for i in a:if not (end+a.index(i)+1)%m:b.append(i)# print(i, end=' ') # print the order of removingif a.index(i) == len(a)-1: # last man of sequenceend = (end+a.index(i)+1)%m# remove elements in b from afor i in b:a.remove(i)return a[0]# solve the problem by math method
def solve2(N, m):return 0 if N == 1 else (solve2(N-1, m)+m)%N# main function for execution
def main():N, m = 41, 3left1 = solve1(N, m)print('\nThe man left: %d' %left1)left2 = solve2(N, m)+1print('\nThe man left: %d' % left2)main()

  完整的Java代码如下:

import java.util.ArrayList;public class Josephus {public static void main(String[] args) {int N = 41;int m = 3;int left = solve(N, m);System.out.println("\nThe man left is "+left+".");}public static int solve(int N, int m) {ArrayList<Integer> a = new ArrayList<Integer>();int end = 0;for(int i=0; i < N; i++)a.add(i+1);while(a.size() > 1) {ArrayList<Integer> b = new ArrayList<Integer>();for(int i: a) {if ((end+a.indexOf(i)+1)%m == 0)b.add(i);// System.out.print(i+"-->");if(a.indexOf(i) == a.size()-1)end = (end+a.indexOf(i)+1)%m;       }for(Object i: b) {a.remove(i);}}return a.get(0);}}

  本次分享到此结束,欢迎大家交流~~

Josephus Problem的详细算法及其Python, Java语言的实现相关推荐

  1. 银行家算法课程设计java语言_Java语言的银行家算法

    <Java语言的银行家算法>由会员分享,可在线阅读,更多相关<Java语言的银行家算法(12页珍藏版)>请在人人文库网上搜索. 1.湖北中医学院信息技术系 操作系统课程设计操作 ...

  2. java 离散算法_用JAVA语言实现离散数学算法

    用JAVA语言实现离散数学算法 用JAVA语言实现离散数学算法 * 显示离散数学算法的真值表 * 提供将一个中缀合适公式的真值表输出到某一PrintStream流中的功能 * 以单个大写字母表示变量( ...

  3. BWT算法解析及Java语言实现

    BWT算法将原来的文本转换为一个相似的文本,转换后使得相同的字符位置连续或者相邻,之后可以使用其他技术如:Move-to-fronttransform 和 游程编码 进行文本压缩. BWT原理: 1. ...

  4. 算法与数据结构java语言描述 英文版_CVPR2020 |室内设计师失业?针对语言描述的自动三维场景设计算法...

    近日,计算机视觉顶会CVPR 2020接收论文结果公布,从6656篇有效投稿中录取了1470篇论文,录取率约为22%.在<Intelligent Home 3D: Automatic 3D-Ho ...

  5. 排序算法之插入排序--Java语言

    插入排序是一种简单且有效的比较排序算法.在每次迭代过程中算法从输入序列中移除一个元素,并将该元素插入待排序序列的正确位置.重复该过程,直到所有输入元素都被选择一次. 算法优点: a.实现简单 b.数据 ...

  6. HOJ 系统常用功能介绍 部署快速入门 c++ python java编程语言在线自动评测 信息奥赛一本通 USACO GESP 洛谷 蓝桥 CSP NOIP题库

    技术支持微 makytony 服务器配置需求 腾讯云 2H4G 5M 60GB 轻量应用服务器  承载大约 200~400人使用,经过压力测试,评测并发速度可满足130人左右的在线比赛. 系统镜像选 ...

  7. Python JAVA Solutions for Leetcode

    Python & JAVA Solutions for Leetcode (inspired by haoel's leetcode) Remember solutions are only ...

  8. python快速排序算法没看懂_你需要知道的九大排序算法【Python实现】之快速排序...

    五.快速排序 基本思想:  通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序. 算法实现: ​ #coding: ...

  9. Java编程语言学习:Java语言编程的基础知识之Java的变量与数据类型、符号、运算符、数组Array总结之详细攻略

    Java编程语言学习:Java语言编程的基础知识之Java的变量与数据类型.符号.运算符.数组Array总结之详细攻略 目录 Java语言编程的基础知识之Java的变量与数据类型.符号.运算符.数组总 ...

最新文章

  1. 动图图解C语言选择排序算法,含代码分析
  2. flume高可用-failover-模型分析
  3. python编译器怎么运行不在路径中的py文件_对python当中不在本路径的py文件的引用详解...
  4. Javascript——入门基础
  5. mysql数据库是下面哪种类型的数据库_SQL数据库 选择哪个类型的数据库?
  6. OpenResty(nginx)操作redis的初步应用
  7. git单独删除某个文件的所有历史记录
  8. 修改linux文件权限命令:chmod超级详细讲解
  9. 通过C#查询SQLServer数据库超时
  10. smarty3.X新命名规范引起的'Call of unknown method'
  11. 易班自动答题脚本_Python实现手机APP之自动打卡签到详细教程(小白合适)
  12. linux 查看内存 单位,linux ps 内存 单位
  13. 代码对比工具:我最喜欢用的还是这几个
  14. 怎么在线把图片转成PDF?几个步骤轻松转换
  15. Ubuntu18修改系统语言为英文
  16. docker单独挂盘步骤
  17. 常用逻辑门电路及其运算表达式
  18. how to do research
  19. 华硕fx60vm拆机图解_技术编辑处置华硕fx60vm【处理手段】
  20. Ubuntu16.04 获取并启用root账户的方法

热门文章

  1. Eclipse优化之设置不自动弹出控制台和Server
  2. 《树莓派开发实战(第2版)》——1.15 使用蓝牙设备
  3. 解析大型.NET ERP系统 设计异常处理模块
  4. 5月.CN域名注册量持续上涨至1199万个 净增14万
  5. 腾讯布局移动应用商店 总下载量累计达40亿次
  6. ​2018你不得不看的国内CRM软件排行榜
  7. Postfix邮件服务搭建
  8. (11)Xamarin.iOS - 新增iPhone storyboard
  9. Gartner2014年魔力象限(商业智能和分析平台)
  10. WinCE6.0 修改开机Logo方法集锦(二)