约瑟夫问题(循环链表法和公式法)python版

约瑟夫问题

N个人站在一个等待被处决的圈子里。第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个人就是最后的胜利者。

问题描述

输入:n,m。其中n为总人数,依次编号为0,1…n,m为被处决的报数数值。
输出:最后活下来人的编号。

解决方案

1.循环单链表法

用循环单链表去模拟这个过程。n个人看做n个链表节点,节点1的value为1,节点1的next指向节点2,节点2的value为2,节点2的next指向节点3,…,节点n的value为n,节点n的next指向节点1,构成一个循环单链表。然后从节点1开始报数,如果报数到m就被删除,最后剩下的那个节点的value就是活下来人的编号。python代码如下:

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None


def create_linkList(n):
    head = Node(1)
    pre = head
    for i in range(2, n+1):
        newNode = Node(i)
        pre.next= newNode
        pre = newNode
    pre.next = head
    return head


n = 8 # 总的个数
m = 3 # 数的数目
if m == 1: # 如果被处决的报数为1,直接输出最后一个值
    print(n)
else:
    head = create_linkList(n)
    pre = None
    cur = head
    while cur.next != cur: # 终止条件是节点的下一个节点指向本身
        for i in range(m-1):
            pre = cur
            cur = cur.next
        pre.next = cur.next
        cur.next = None
        cur = pre.next
    print(cur.value)

2.公式法

递推公式:
f ( n , m ) = ( f ( n − 1 , m ) + m )   m o d   n f(n,m) =(f(n-1,m)+m)\ mod\ n f(n,m)=(f(n1,m)+m) mod n
f ( 1 , m ) = 0 f(1,m) = 0 f(1,m)=0
代码如下:

n = 8 # 总的个数
m = 3 # 数的数目
if m == 1: # 如果被处决的报数为1,直接输出最后一个值
    print(n)
else:
    i = 0
    a = list(range(n))
    while len(a) > 1:
        i =(i+2)%len(a)
        del a[i]
    print(a[0] + 1)

参考

约瑟夫问题-维基百科

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
循环链表是解决约瑟夫问题的一种常见方。下面是一个使用Java循环链表解决约瑟夫问题的示例: ```java class Node { int data; Node next; public Node(int data) { this.data = data; } } class CircularLinkedList { private Node head; private Node tail; public void add(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; tail = newNode; tail.next = head; } else { tail.next = newNode; tail = newNode; tail.next = head; } } public void remove(Node node) { if (head == null) { return; } if (head == node) { head = head.next; tail.next = head; } else { Node current = head; while (current.next != node) { current = current.next; } current.next = node.next; if (node == tail) { tail = current; tail.next = head; } } } public void josephus(int k) { Node current = head; while (current.next != current) { for (int i = 1; i < k; i++) { current = current.next; } System.out.print(current.data + " "); remove(current); current = current.next; } System.out.println(current.data); } } public class Main { public static void main(String[] args) { CircularLinkedList list = new CircularLinkedList(); int n = 7; // 总人数 int k = 3; // 报数为3的人出列 for (int i = 1; i <= n; i++) { list.add(i); } System.out.println("出列顺序:"); list.josephus(k); } } ``` 这段代码中,我们首先定义了一个`Node`类来表示循环链表的节点,然后定义了`CircularLinkedList`类来实现循环链表的操作。在`josephus`方中,我们使用循环链表模拟约瑟夫问题的解决过程,每次找到第k个节点并移除,直到只剩下一个节点为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值