约瑟夫问题(历史战争问题)

直观理解

老外视频讲解
模拟器演示

约瑟夫问题 数学姥公众号 讲的最清楚 背景及,推倒过程讲解得很清晰,旨在提高人们对数据的兴趣

简单说下: 几个人围成一圈(循环队列), 第一个人开始报数 1 2 1 2, 依次进行,喊2的被杀掉. 如果人数是n,则最后剩下几号?

约瑟夫斯问题是个蛮好玩的问题。这个问题来源于一个犹太叛徒,约瑟夫斯是犹太人,参与了对罗马的起义,并被任命为起义部队的军事长官。不过在后来罗马军团的进攻下,犹太人的起义很快失败了,约瑟夫斯带领这39名犹太士兵躲到了一个山洞中,山洞则被罗马人包围。士兵们坚贞不屈,宁可死也不肯投降,然而约瑟夫斯不想死,又不敢说出来。于是约瑟夫斯利用了犹太教中关于自杀耻辱的教义,说咱们不能自杀,咱们可以互相杀,怎么互相杀,谁来杀呢?这样

40人围成一圈,然后连续1,2,1,2……报数,所有报2的被同伴杀死,直到最后一个,最后一个自杀者承担教义中自杀的耻辱。约瑟夫斯是个数学家,他当然很快就知道自己应该站在哪个位置而不会被杀死。当所有人都被杀死后,他走出山洞,投降了罗马人。

那么,现在的问题是,就按照1212报数,报2被杀死的规则,当人数n不止40时,站在哪个位置能最后活下来?

最终推倒出的解决公式:

如果n个人,则最终f(n)号活下来.

栗子1: f(100)=f(64+36)=2*36+1=73,100

这里为何64+36呢? 2^6=64, 2^7=128>100, 所以只能36了.
依据公式,可以推倒出 n = 100, f(100)=73

栗子2: n = 6,最终存活下第5个Susan
["Bill", "David", "Kent", "Jane", "Susan", "Brad"]

搞清楚了这个问题是啥,和解题思路.后用程序来实现它.

  • 不得不说,数据这玩意如果不用符号来标识, 那么语句废话再多也描述不到位问题.
  • 核心乐趣是推倒这个问题通用算法的结论. 其他的都是锦上添花的作用. 有种朝闻道,夕死可矣的感觉

用Python实现的数据结构与算法:队列

队列: 对尾加,对首出

remainder 余数

bin 二进制
dec 十进制
rem 余数

Queue 队列
enqueue 排队 对尾
dequeue 出对 对首

front 在前面
rear  在后面

值得注意的是,Queue类只实现了简单队列,上述问题实际上需要用循环队列来解决。在报数过程中,通过“将(从队首)出队的人再入队(到队尾)”来模拟循环队列的行为。具体代码如下:

#!/usr/bin/env python
# coding=utf-8

# 实现每次 对尾添加  对首出现

class Queue:
    def __init__(self):
        self.arr = []

    def push(self, i):
        self.arr.append(i)

    def pop(self):
        return self.arr.pop(0)

    def size(self):
        return len(self.arr)

# arr1 = Queue()
# arr1.push(1)
# arr1.push(2)
# arr1.push(3)
# arr1.pop()
# print(arr1.arr)

## 解决约瑟夫问题
#### 模拟循环队列  对首出队 对尾追加  弹出对首 返回弹出对首

def josephus(arr1, num):
    ## 入队
    q = Queue()
    for name in arr1:
        q.push(name)

    # 对首出列, 添加到对尾
    while q.size() > 1:
        for i in range(num):
            q.push(q.pop())
        q.pop()
    return q.pop()

print(josephus(["Bill", "David", "Kent", "Jane", "Susan", "Brad"], 3))

[py]约瑟夫问题-循环队列的更多相关文章

  1. 约瑟夫环-循环队列算法(曾微软,google笔试题)

    这也是我们聚会时常常做的游戏之一. 算法思路: 此处我使用循环链表模拟人围城一圈,每一个结点代表一个人.链表是一个有序链表,链表结点数据域是一个整型,代表人的序号.出局等同于链表删除元素,每次出局后重 ...

  2. 使用 JavaScript 实现基本队列、优先队列和循环队列

    1.基本队列的实现 基本队列的方法中,包含了 ①向队列(尾部)中添加元素(enqueue).②(从队列头部)删除元素(dequeue).③查看队列头部的元素(front).④查看队列是否为空(isEm ...

  3. Javascript数据结构与算法--队列(顺序队列、优先队列、循环队列)的实现与用法

    前言 队列和栈非常类似,前面已经讲过了栈的实现与用法,现在我们来说说队列. 队列介绍 队列遵循FIFO(First In First Out,先进先出)原则的一组有序的项. 队列是一种特殊的线性表,特 ...

  4. python 循环队列的实现

    最近在做一个东西的时候发现需要用到循环队列,实现先进先出(FIFO),不断往里面添加数据,当达到某个限定值时,最先进去的出去,然后再添加.之后需要对队列里面的内容进行一个筛选,作其他处理.首先我想到了 ...

  5. C++数组实现的循环队列

    #include<iostream> #include <string> /* 功能:数组实现的循环队列,C++实现,学习参考 */ using namespace std; ...

  6. C ~ 链式队列与循环队列

          此处的链式与循环队列可以应用于BFS和树的层序遍历.下面是对其结构和基本操作的程序描述. 1.循环队列 解决循环队列的队空和队满的方法: [1].增加一个参数count,用来记录数组中当前 ...

  7. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  8. Atitit.提升软件稳定性---基于数据库实现的持久化 循环队列 环形队列

    Atitit.提升软件稳定性---基于数据库实现的持久化  循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...

  9. 循环队列+堆优化dijkstra最短路 BZOJ 4152: [AMPPZ2014]The Captain

    循环队列基础知识 1.循环队列需要几个参数来确定 循环队列需要2个参数,front和rear 2.循环队列各个参数的含义 (1)队列初始化时,front和rear值都为零: (2)当队列不为空时,fr ...

随机推荐

  1. springbatch---->springbatch的使用(六)

    前面的例子step都是线性的流程,这里我们提供一个非线性的流程,也就是根据不同的状态做不同的流程step处理.万一有天悔恨变得太现实太世故太麻木,说不定能从回忆中重拾随兴飞翔. step非线性的流程 ...

  2. centos 安装 Vagrant

    使用的软件: 1. CentOS:  CentOS release 6.4 (Final) 2. Vagrant: vagrant_1.2.2_i686.rpm 3. Virtualbox: Virt ...

  3. canvas练习 - 圆

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. Ubuntu Eclipse配置Python开发环境

    一 在Eclipse中安装pydev插件 启动Eclipse, 点击Help->Install New Software... 在弹出的对话框中,点Add 按钮. Name中填:Pydev Lo ...

  5. php guzzle post async

    use GuzzleHttp\Pool;use GuzzleHttp\Client;//use GuzzleHttp\Psr7\Request;use Psr\Http\Message\Respons ...

  6. css笔记——文本样式

    聊聊text-decoration.text-indent.text-transform.letter-spacing.word-spacing.vertical-align.下面是一些常用设置文本样 ...

  7. sencha touch 在安卓中横屏、竖屏切换 应用崩溃问题

    答案来至于 Sencha Touch 交流 @周旭 这是由于横竖屏转换导致activity重跑onCreate方法导致的,有两种解决方案:1.横竖屏转换的时候不要重新跑onCreate方法,这个可以在 ...

  8. C语言位操作--判断整数是否为2的幂

    unsigned int v; // 判断v是否为2的幂 bool f; // f为判断的结果 f = (v & (v - 1)) == 0; // 结果为0表示不是2 的幂 // 改变表示方 ...

  9. xcode vs visual studio

    不得不说,VS做的还是不错的,尤其是对C++的debug功能傲视群IDE. 一个VS与XCODE的对比. http://development-software.findthebest.com/com ...

  10. iOS - 原生的CIFilter生成二维码和条形码

    使用CIFilter可以不引入任何第三方库,就可以生成想要的二维码和条形码,今天简单的介绍一下使用CIFilter生成二维码和条形码.系统CIFilter生成的二维码和条形码的大小有时并不能满足需求, ...