约瑟夫问题及求解方法

用循环队列求解约瑟夫环问题 用循环队列求解约瑟夫环问题 大家好,这次我们来求解求解约瑟夫环问题,并对比用循环队列和用普通形式求解之间的不同之处。也欢迎各位大佬指正。 目录如下可快速查阅问题描述循环队列求解算法描述程序清单运行结果普通形式求解算法描述程序清单运行结果对比分析 问题描述 设有n个人站成一圈,其编号为1~n。从编号为1的人开始按顺时针方向1、2……循环报数,数到m的人出列,然后从出列者的下一个人重新开始报数,数到m... 阅读详情

什么是约瑟夫问题?

约瑟夫问题是一个经典的数学难题,其一般形式可以描述为:

  • n个人(编号从1到n),围坐在一张圆桌周围。
  • 从第一个人开始报数,报到m的人出列;
  • 然后从出列者的下一个人开始重新报数,报到m的人又出列;
  • 依此规律重复进行直到剩余最后一个人。所求即为胜利者的编号。

在这里插入图片描述


求解方法

  1. 枚举

如果使用枚举法列出所有可能的情况计算,时间和空间复杂度会非常大,因此需要寻找更高效的算法。

  1. 循环链队
  • 从存储结构看,队分为顺序队与链队两种。
    顺序队用一维数组连续存放队列元素,容量固定;
    链队的容量无法预先估计,可动态变化。在链队中我们设一个头结点,头指针始终指向头结点,尾指针指向队尾元素。

  • 我们将n个人用链表相连,并采用类似循环队列的方式进行报数。

  • 具体来说,每次从当前节点开始逐个报数,当数到m时,删除该节点,从下一个节点重新开始报数。

  • 这个过程重复n-1次,最终留下的节点即为胜利者。

注意:在实现过程中还需要采取一些技巧来提高效率。

  • 例如,我们可以使用一个指针记录当前轮次的最后一个节点,以减少不必要的遍历。
  • 此外,由于链表在删除某个节点时需要先找到该节点的前驱节点,因此我们需要采用双向链表而非单向链表。

代码实现

  • C语言实现:
#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{		//链式队列的结点 
	int data;
	struct LNode * next;
}LinkList;
int n = 41, m = 3;

//1、初始化循环单链表
LinkList *init_LinkList(LinkList *L){
	int i = 1;
	L = (LinkList*)malloc(sizeof(LinkList));
	LinkList *p=L;
	LinkList *pNew;
	
	scanf("%d", &n);
	if(n != 0)	{
		while(i <= n)		{
			pNew = (LinkList *)malloc(sizeof(LinkList));
			pNew->data = i++;
			p->next = pNew;
			p = pNew;
		}
		pNew->next=L->next;
		
	}

	free(L);			//删除头结点 
	return pNew->next;	//返回第一个数的指针
}
void del_sque(int n,LinkList *p){
	LinkList * t;

	while(p!=p->next)	{
		for(int i=1;i<m-1;i++)
			p=p->next;
		printf("%d->",p->next->data);

		t=p->next;
		p->next=t->next;
		free(t);

		p=p->next;
	}
	printf("%d\n",p->data);

	return;
}

int main(){

	LinkList *Head = NULL;
	Head = init_LinkList(Head);		//创建无头结点的循环链表 
	del_sque(n,Head);				//求解约瑟夫问题 
	
	return 0;
}
  • python实现:
class ListNode:
    def __init__(self, value):
        self.value = value
        self.next = None
        self.prev = None

def josephus(n, m):
    # 构建初始链表
    head = ListNode(1)
    cur = head
    for i in range(2, n+1):
        new_node = ListNode(i)
        cur.next = new_node
        new_node.prev = cur
        cur = new_node
    tail = cur           # 记录末尾节点

    # 进行删除操作,直至只剩1个节点
    cur = head
    while cur != cur.next:
        # 找到m-1个节点
        for _ in range(m-1):
            cur = cur.next
        # 删除当前节点
        prev, next = cur.prev, cur.next
        if prev:
            prev.next = next
        if next:
            next.prev = prev
        # 更新cur指针和tail指针
        cur = next
        tail = prev

    return tail.value  # 返回唯一留下的节点编号

# 测试代码
print(josephus(7, 3))   # 输出4
你能找到的最详细约瑟夫环的数学推导 约瑟夫环问题是这样的: 0, 1, …, n - 1 这 n 个数字排成一个圆圈,从数字 0 开始,每次从这个圆圈里删除第 m 个数字。求出这个圆圈里剩下的最后一个数字。 例如,0、1、2、3、4 这 5 个数字组成一个圆圈,从数字 0 开始每次删除第 3 个数字,则删除的前 4 个数字依次是 2、0、4、1,因此最后剩下的数字是 3。如下图所示。 解... 阅读详情

相关推荐

约瑟夫问题的链表解法(4种)

简单的玩意儿。

weixin_60202007的博客 1234

约瑟夫问题_公式原理详解

每次增加一个人,我们第一轮的报数被指定的必定是新加入的人。

小黯 3万+

约瑟夫斯问题的求解方法

约瑟夫斯问题 1. 问题介绍   这个问题是以弗拉瓦斯 约瑟夫斯的名字命名的。约瑟夫斯是一个著名的犹太历史学家,参加并记录了公元66-70年的犹太人反抗罗马的起义。约瑟夫斯作为一个将军,设法守住了裘达伯特的堡垒达47天之久,但在城市陷落之后,他在和40名顽强的战士在附近的一个洞穴中避难。在那里,一些反抗者表决说“要投降毋宁死”。于是,约瑟夫斯建议每个人应该轮流杀死他旁边的人,而这个顺序是是由抽签决...

XiaoGuYing的博客 6800

约瑟夫环问题

一、问题描述 约瑟夫环问题是一个很经典的问题:一个圈共有N个人(N为不确定的数字),第一个人的编号为0或者1(两个都可以,看你的程序如何编写),假设这边我将第一个人的编号设置为1号,那么第二个人的编号就为2号,第三个人的编号就为3号,第N个人的编号就为N号,现在提供一个数字M,第一个人开始从1报数,第二个人报的数就是2,依次类推,报到M这个数字的人出局,紧接着从出局的这个人的下一个人重新开始从1报数,和上面过程类似,报到M的人出局,直到N个人全部出局,请问,这个出局的顺序是什么? 举一个简单的例子:假.

xiaoxi_hahaha的博客 11万+

【Ultrascale+ MPSOC学习记录】10、PS端以太网使用lwip

还是参考ALINX教程,学习PS端以太网如何使用,从教程中可以看到,开发板使用了一个xilinx默认不支持的phy JL2121,所以需要修改lwip的库源码。

ryo891012的博客 869

详解STM32F407双重ADC同步采集与DMA传输的配置技巧及实战应用

本文详细解析了STM32F407双重ADC同步采集与DMA传输的配置技巧及实战应用。通过CubeMX配置、代码实现和常见问题解决方案,帮助开发者高效实现多通道数据同步采集,提升工业自动化和嵌入式系统的数据采集效率与精度。

ii567的博客 359

约瑟夫环问题求解方法总结

约瑟夫环问题 n个人围成圈,从第一个人开始报数,数到k的人自杀。然后自杀的下一个人接着从1开始数,一直到剩下最后一个人。 一,使用队列模拟过程 首先将这n个人入队,然后开始计数,并且不断地出队,如果当前这个人是k的倍数的话就杀掉,如果不是k的倍数就再次入队。 代码如下: #include <iostream> #include <queue> using namespac...

qq_43227036的博客 510

飞常准小程序接口逆向分析:如何破解航班查询的签名机制

本文深度解析了飞常准小程序航班查询接口的安全机制,重点剖析了其基于MD5和参数排序的签名算法。通过逆向分析核心代码,详细阐述了签名生成流程,并提供了Python实现的签名生成器与调试技巧,为开发者理解与模拟此类接口调用提供了实战指南。

zz67890的博客 524

约瑟夫问题三种求解方法

约瑟夫问题是个很经典的问题,目前网上求解方法较多,主要有数组法、循环队列法、指针链表法三种求解思路,下面给出三种求解方法的原创的标准C语言代码,含详细注释,供C语言和数据结构的初学者学习,本程序在VC 6.0下编译通过。 约瑟夫问题的来历:     据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹

hb2008hahaha的专栏 3096

别再折腾老教程了!树莓派4B/5最新系统(Raspberry Pi OS Bookworm)红外遥控配置,用gpio-ir驱动一次成功

本文详细介绍了树莓派4B/5在最新Raspberry Pi OS Bookworm系统下配置红外遥控的完整指南,摒弃过时的lirc-rpi驱动,采用现代gpio-ir驱动方案。从硬件连接到软件配置,提供10分钟快速上手指南,涵盖驱动加载、信号测试、按键映射及高级应用场景,帮助用户高效完成红外遥控配置。

weixin_42520909的博客 439

企业级大模型落地:私有化部署的安全合规全流程实战指南

摘要:本文针对企业在大模型私有化部署中面临的数据泄露、合规风险及系统稳定性难题,提出一套覆盖数据安全、模型合规、审计追踪与灾备方案的全流程解决方案。通过双加密管道(国密SM4传输加密+AES-GCM存储加密)、SGX可信执行环境等技术,实现数据全生命周期保护;结合等保2.0三级要求与《生成式AI服务管理暂行办法》,提供合规性实施细则;并给出本地GPU集群、混合云、边缘推理盒子三种企业级部署方案及成本模型。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 894

求解约瑟夫问题两种方法

1:500个小孩围成一圈,从第一个开始报数:1,2,3,1,2,3,1,2,3,……每次报3的小孩退出  问最后剩下的那个小孩,在以前500人里是第几个??? 很经典的一个约瑟夫问题,我看了几个大神的算法,用了点时间才搞懂一个大神用的递归思想,非递归算法的求解方法,确实厉害。 首先假设这里有10个小孩,我们给他们编号为: 0 1 2 3 4 5 6 7 8 9 那么第一次

荼靡~ 1313

STM32F103待机模式原理与低功耗实战指南

待机模式是嵌入式系统实现超低功耗的核心机制,其本质是通过切断内核域电源(VDD/VDDA)实现微安级静态电流,区别于睡眠/停止模式的状态保持特性。原理上依赖电源域隔离、WKUP引脚事件唤醒与RTC备份域协同,技术价值在于支撑电池供电设备长达数年续航。典型应用场景包括物联网传感器节点、智能电表、便携医疗设备等对功耗极度敏感的终端。工程落地需严格遵循GPIO模拟输入配置、唤醒标志清除、备份域解锁等关键步骤,避免因漏电或误唤醒导致实测电流超标。本文以STM32F103为例,深入解析待机模式的硬件基础与HAL库实现

weixin_32999557的博客 64

趣味问题 约瑟夫圈的数组求解方法

假设n个人围成一个圈,从1开始报数,到3就把报数的人踢出,然后从1开始,一直循环下去,直到最后一个人,请问这个 人是第几号人? 这就是约瑟夫圈问题,这个问题的求解方法比较多,今天介绍一下它的数组求解方法。 1#include 2 int main() 3 { 4 int num = 0,out = 0,i = 0,n; //num为报号,到3清零;ou

rocky_56X的博客 505

电阻基础知识及应用电路仿真(Multisim)

本文围绕硬件工程师必备的电阻知识,从基础知识、实操、应用仿真三方面做系统讲解:基础上明确电阻的核心参数、分类、串并联计算及核心特性;实操中详解贴片/色环电阻的阻值读取、贴片封装换算,重点区分0Ω电阻(贴装跳线,实现功能选通/调试等)与磁珠(高频吸噪)的差异及选型;应用上介绍限流、分压、上拉/下拉、阻抗匹配、过压/过流保护五大典型电路的设计公式、选型原则和实操要点,同时给出电阻通用的选型、测量和布线设计规范,形成完整的电阻应用知识体系。

XU157303764的博客 2762

微信小程序 - 解决微信支付报错 requestPayment:fail no permission 原因分析及排查处理(支付失败出错,无法唤起支付弹框面板,微信支付API报错请求付款:失败无权限)

微信小程序,微信支付,支付报错,errMsg: "requestPayment:fail no permission",支付失败,支付权限没问题,微信小程序支付报错,检查了appid正确依旧不行,微信小程序支付异常,苹果ios手机,安卓手机,开发者工具模拟器,最新解决教程,小程序wx.requestPayment报错/无响应,小程序支付 requestPaym,微信小程序认证,真机运行,小程序微信支付提示错误,微信小程序里使用微信支付错误提示,微信小程序支付异常,微信支付弹框拉不起来,小程序支付api,都检

🏆 前端领域优质创作者 1万+

2种方法求解约瑟夫环问题

问题:n个人围成一圈缝m报数,数到m的出列,后面的人开始继续从1开始,数到m的出列,问最后剩下的一个人的序号是多少。   一.循环单链表求解 //循环队列求解约瑟夫问题 #include #include typedef struct student { i

ERIC的编程之路 2400

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

约瑟夫环出圈问题三种求解方法

#coding=utf-8 # 递归直接求出 def fun_recursion(m,k): """ f[1]=0; f[i]=(f[i-1]+k)%i = (f[i-1] +m%i) % i = (f[i-1] + m) % i ; (i>1) :param m: 长度 :param k: 第k数出环 :return: """

马凡贺的博客 5520

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

约瑟夫环问题(数学方法求解)

问题描述: n个人(编号0 ~ n-1),从0开始报数,报到m-1的退出,剩下的人继续从0开始报数。求胜利者的编号。 分析: 第一个出列的人编号是m-1,剩下的n-1个人就又组成了一个新的约瑟夫环(从编号为k = m % n的人开始),有: 出列前的编号 k k+1 k+2 … n-2 n-1 0 1 2 … k-2 出列后的编号 0 1 2 … … n-2 这样就重...

默的博客 1108

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

三种方法求解约瑟夫环问题

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。 方法1:使用stl::list模拟环形链表,参考剑指offer 代码: #include #include using namespace std; i

byf_study_alway的专栏 2101

求解约瑟夫问题(Joseph Problem)的数学方法 from 御剑晨风

http://alexxyjiang.blog.163.com/blog/static/11713572120109210942883/ 约瑟夫问题(Joseph Problem): n个人(编号由0, 1, ..., n-1)围成一圈,由编号0的人从1开始报数,报到m的退出,剩下的人继续从1开始报数,直到圈内只剩余1人,求胜利者的编号。(n>0, m>0) ----...

weixin_30497527的博客 190

约瑟夫问题的python代码及注释_约瑟夫问题的Python和C++求解方法

么是约瑟夫问题?约瑟夫问题是一个有趣的数学游戏,游戏规则如下:1、N个人围成一个圈,编号从1开始,依次到N。2、编号为M的游戏参与者开始报数,报数从1开始,后面的人报数接龙,直到K为止,报数为K的人将出局。3、出局者的下一个玩家接着从1开始报数,如此循环,直到剩下一个玩家时游戏结束,这个玩家就是游戏获胜者。那么问题来了,哪个编号是游戏获胜者呢?下面通过简单的几行python代码来解决这个问题:#!...

weixin_42237496的博客 802

python约瑟夫环问题及求解方法问题拓展、命令库包装

最近鼠鼠的导师开始培训鼠鼠python以及代码规范,抛出了约瑟夫环问题问题作为一个例子,让我们实现,要求符合pep8规范以及用类实现,拥有一些拓展性功能。文件拓展了约瑟环问题,使用类的方法实现,采用了命令调度机制实现了对约瑟夫环问题的动态操作。使用命令调度机制也可以参考本文

weixin_52342399的博客 459

C++面向对象方法求解约瑟夫环问题

约瑟夫问题有很多种解法及其变种,这里的约瑟夫环问题是这样的: [b]约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列.[/b] 大多数的约瑟夫环问题解法是利用面积过程的方法编写的(其实我没有看过多少

心清的专栏 5124

数学方法求解约瑟夫问题(zz)---n久前的一个问题了 【摘自旧博】

数学方法求解约瑟夫问题---n久前的一个问题了。。 最近又遇到,竟然想不出具体程序。。。。。。只记得大概。。-,- 不得以又翻了翻以前的老帖子。。。 特此到blog转贴以下,以免以后又忘记了。。。 ps:几天不练,大脑就迟钝了。。。。晕菜儿~~~~~-------------------------------------------------------

wavemoon的专栏 746
上一篇: PageRank原理及C语言实现
下一篇: 利用栈和队列共同解决迷宫问题
为梦而生~
博客等级 码龄6年 2484粉丝 129原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为梦而生~

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值