三种方法解决Josephus问题

数据结构和算法--python 专栏收录该内容
2 篇文章 0 订阅

前景

由于之前数据结构底子很薄,现在开始补咯~虽然进展缓慢,慢慢来嘛~今天遇到的是josephus问题

问题阐述

假设有n个人围坐一圈,现在要求从第k个人开始报数,报到第m个数的人退出。然后从下一个人开始继续报数并按照同样的规则退出,直至所有人都退出。按照顺序输出各出列人的编号

解决

# 问题描述
# 假设有n个人围坐一圈,现在要求从第k个人开始报数,报到第m个数的人退出。然后从下一个人开始继续报数并按照同样的规则退出,直至所有人都退出。按照顺序输出各出列人的编号


# 解法1.基于数组。使用0代表出列的人
def josephus(n, k, m):
    lista = []
    # 一共有n个人,先编好序号
    for i in range(1, n+1):
        lista.append(i)
    # 一共要出列n个人,person 是正在报数的人的下标,最后要输出各列人的编号
    person = k-1
    for time in range(n):
        # count作为计数器,每报一个数count自增1
        count = 0
        # 游戏执行的条件,只要没报到m个数
        while count != m:
            if lista[person] != 0:
                count += 1
            if count == m:
                # 第m个人出列,记为0
                lista[person] = 0
                yield person+1
            person += 1
            person %= n


# 基于Python的列表
def fun(n, k, m):
    lista = list(range(1, n+1))
    i = k-1
    # 每次都要出列一个人,所有人的总数会随之减少
    for number in range(n, 0, -1):
        i = (i+m-1) % number
        person = lista.pop(i)
        yield person


# 基于循环单链表
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None


class LoopList:
    def __init__(self):
        self.tail = None

    def add(self, data):
        if self.tail is None:
            self.tail = Node(data)
            self.tail.next = self.tail
        else:
            tmp = Node(data)
            tmp.next = self.tail.next
            self.tail.next = tmp

    def append(self, data):
        self.add(data)
        self.tail = self.tail.next

    def bianli(self):
        current = self.tail.next
        while current is not self.tail:
            print(current.data)
            current = current.next
        print(current.data)

    # 前端弹出
    def pop(self):
        # 如果就是一个结点的话
        tmp = self.tail.next
        if tmp is self.tail:
            self.tail = None
        else:
            self.tail.next = tmp.next
        return tmp.data

    # 尾端弹出
    def pop2(self):
        current = self.tail.next
        while current.next is not self.tail:
            current = current.next
        current.next = self.tail.next
        self.tail = current


class Josephus(LoopList):
    # 尾指针作为正在报数的那个人,每一轮报数作为一次指针的移动(旋转)
    def spin(self, n):
        for i in range(n):
            self.tail = self.tail.next

    def __init__(self, n, k, m):
        super(Josephus, self).__init__()
        for i in range(1, n+1):
            self.append(i)
        # 初始化到第k个人进行报数
        self.spin(k-1)
        while self.tail is not None:
            # 旋转到报第m个数的人
            self.spin(m-1)
            print(self.pop())

结果测试:

a = LoopList()
a.append(12)
a.append(13)
a.append(14)
a.pop2()
a.bianli()
Josephus(10, 1 ,3)

12
13
3
6
9
2
7
1
8
5
10
4

  • 3
    点赞
  • 0
    评论
  • 16
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

河海哥yyds

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值