当前位置: 首页 > news >正文

约瑟夫环递归算法详解与实现

一、引言

约瑟夫环问题是一个著名的理论问题,其背景是在古罗马时期,有n个犯人被围成一个圈,从第一个人开始报数,每次报到m的人将被处决,然后从下一个人开始重新报数,直到所有人都被处决。这个问题可以用递归算法来解决,本文将详细介绍约瑟夫环问题的递归算法,并给出C++代码实现。

二、约瑟夫环问题描述

有n个人围成一圈,从第一个人开始报数,每次报到m的人将被淘汰出局,然后从下一个人开始重新报数,直到最后只剩一个人为止。这个最后留下来的人被称为“幸运者”。我们需要找出这个幸运者的位置(即他在初始排列中的序号)。

三、递归算法思想

对于约瑟夫环问题,我们可以使用递归算法来解决。递归算法的基本思想是将问题分解为更小的子问题,然后逐个解决这些子问题,最终得到原问题的解

在约瑟夫环问题中,我们可以将原问题分解为n-1个人的子问题。假设我们知道在n-1个人中,谁是幸运者(即他在子问题中的序号),那么我们可以通过这个信息来找出在n个人中谁是幸运者。

具体来说,我们可以这样想:在n个人中,第一个被淘汰的人是第m个人(从第一个人开始报数)。当这个人被淘汰后,剩下的n-1个人形成了一个新的圈。这个新圈中的第一个人(即原圈中的第m+1个人)成为了新的起点。然后,我们在这个新圈中继续执行约瑟夫环问题的规则,直到找到幸运者。

在递归过程中,我们需要记录两个关键信息:一是当前圈中的人数n,二是报数的步长m。这两个信息将作为递归函数的参数传递给下一层递归。

四、递归算法实现

#include <iostream>
using namespace std;// 递归函数,返回在n个人中,报数步长为m时的幸运者的序号
int josephus(int n, int m) {if (n == 1) {// 当只剩下一个人时,他就是幸运者return 1;} else {// 否则,计算在第n个人被淘汰后,新的圈中幸运者的序号// 新的圈中的人数为n-1,报数步长仍为m// 由于第m个人被淘汰,所以新的圈中的幸运者在原圈中的序号为 (josephus(n-1, m) + m - 1) % n + 1// 注意:这里使用了取模运算和加1操作,以确保序号在1到n之间return (josephus(n-1, m) + m - 1) % n + 1;}
}int main() {int n, m;cout << "请输入总人数n和报数步长m:" << endl;cin >> n >> m;// 调用递归函数求解幸运者的序号int survivor = josephus(n, m);cout << "幸运者的序号是:" << survivor << endl;return 0;
}

五、算法分析

  1. 时间复杂度:递归算法的时间复杂度与递归的深度有关。在约瑟夫环问题中,递归的深度为n(总人数),因此时间复杂度为O(n)。虽然递归算法在某些情况下可能不如迭代算法高效,但它提供了更清晰的思维方式和更简洁的代码实现。
  2. 空间复杂度:递归算法的空间复杂度主要由递归栈的深度决定。在约瑟夫环问题中,递归栈的深度也为n(总人数),因此空间复杂度为O(n)。然而,在实际应用中,由于现代计算机的内存资源非常丰富,这个空间复杂度通常是可以接受的。

六、递归算法的优化

虽然上述递归算法已经能够解决约瑟夫环问题,但在某些情况下,我们可能希望进一步优化算法的性能。以下是一些可能的优化方法:

  1. 尾递归优化:在某些编程语言中(如C++),递归函数在调用自身时可能会产生额外的栈空间开销。为了减少这种开销,我们可以使用尾递归优化技术。尾递归优化允许编译器在调用递归函数时重用当前函数的栈帧,从而节省空间。然而,需要注意的是,C++标准并未强制要求编译器实现尾递归优化,因此在实际应用中可能无法获得预期的效果。
  2. 迭代算法:与递归算法相比,迭代算法通常具有更低的时间复杂度和空间复杂度。对于约瑟夫环问题,我们可以使用迭代算法来求解幸运者的序号。迭代算法的基本思想是使用一个循环来模拟报数和淘汰的过程,直到只剩下一个人为止。这种算法的时间复杂度和空间复杂度均为O(n),但在实际应用中通常具有更好的性能表现。

七、迭代算法实现

#include <iostream>
#include <vector>
using namespace std;// 迭代算法求解约瑟夫环问题
int josephusIterative(int n, int m) {if (n == 0 || m == 0) {return -1; // 输入无效,返回-1表示错误}vector<int> circle(n);for (int i = 0; i < n; ++i) {circle[i] = i + 1; // 初始化环,从1开始编号}int index = 0; // 当前位置索引while (n > 1) {// 向前移动m-1步for (int i = 0; i < m - 1; ++i) {index = (index + 1) % n;}// 淘汰当前位置的人cout << "淘汰的人序号是:" << circle[index] << endl;circle[index] = 0; // 标记为已淘汰// 向前移动一步到下一个位置index = (index + 1) % n;// 更新剩余人数n--;// 压缩环,将所有非零元素向前移动int j = 0;for (int i = 0; i < circle.size(); ++i) {if (circle[i] != 0) {circle[j++] = circle[i];}}// 更新环的大小circle.resize(j);}// 返回幸运者的序号for (int i = 0; i < circle.size(); ++i) {if (circle[i] != 0) {return circle[i];}}return -1; // 如果找不到幸运者,返回-1表示错误(实际上这种情况不会发生)
}int main() {int n, m;cout << "请输入总人数n和报数步长m:" << endl;cin >> n >> m;// 调用迭代算法求解幸运者的序号int survivor = josephusIterative(n, m);cout << "幸运者的序号是:" << survivor << endl;return 0;
}

八、算法对比

  1. 递归算法:递归算法具有简洁的代码实现和清晰的思维方式,但在处理大规模数据时可能会导致栈溢出或性能下降。此外,递归算法的空间复杂度通常较高,因为需要存储每一层递归的局部变量和返回地址。

  2. 迭代算法:迭代算法通过循环来模拟报数和淘汰的过程,避免了递归调用带来的额外开销。迭代算法的时间复杂度和空间复杂度均为O(n),且在实际应用中通常具有更好的性能表现。此外,迭代算法还可以方便地处理大规模数据,而无需担心栈溢出的问题。

九、结论

本文介绍了约瑟夫环问题的递归算法和迭代算法,并给出了相应的C++代码实现。递归算法具有简洁的代码实现和清晰的思维方式,但在处理大规模数据时可能存在性能问题。迭代算法通过循环来模拟报数和淘汰的过程,避免了递归调用的额外开销,并在实际应用中通常具有更好的性能表现。因此,在实际应用中,我们可以根据问题的规模和需求选择合适的算法来解决约瑟夫环问题。

相关文章:

约瑟夫环递归算法详解与实现

一、引言 约瑟夫环问题是一个著名的理论问题&#xff0c;其背景是在古罗马时期&#xff0c;有n个犯人被围成一个圈&#xff0c;从第一个人开始报数&#xff0c;每次报到m的人将被处决&#xff0c;然后从下一个人开始重新报数&#xff0c;直到所有人都被处决。这个问题可以用递…...

互联网应用主流框架整合之构建REST风格的系统

REST&#xff08;Representational State Transfer&#xff09;&#xff0c;中文译为“表述性状态转移”&#xff0c;是由Roy Fielding博士在他的博士论文中提出的一种软件架构风格&#xff0c;特别适用于网络应用的设计。REST不是一个标准&#xff0c;而是一种设计原则和约束集…...

vue3-自定义指令来实现input框输入限制

文章目录 前言具体实现分析主要部分详细解析导入和类型定义mounted 钩子函数unmounted 钩子函数指令注册使用 总结 前言 使用vue中的自定义指令来实现input框输入限制 其中关键代码强制触发input &#xff0c;来避免&#xff0c;输入规则外的字符时&#xff0c;没触发vue的响…...

MySQL日志——redolog

redo log&#xff08;重做日志&#xff09; 为什么需要redo log&#xff1f; 在mysql提交一个事务后&#xff0c;这个事务所作的数据修改并不会直接保存到磁盘文件中&#xff0c;而是先保存在buffer pool缓冲区中&#xff0c;在需要读取数据时&#xff0c;先从缓冲区中找&…...

Python热涨落流体力学求解算法和英伟达人工智能核评估模型

&#x1f3af;要点 &#x1f3af;平流扩散简单离散微分算子 | &#x1f3af;相场模拟&#xff1a;简单旋节线分解、枝晶凝固的 | &#x1f3af;求解二维波动方程&#xff0c;离散化时间导数 &#x1f3af;英伟达 A100 人工智能核性能评估模型 | &#x1f3af;热涨落流体动力学…...

【C语言】数组参数和指针参数详解

在写代码的时候难免要把【数组】或者【指针】传给函数&#xff0c;那函数的参数该如何设计呢&#xff1f; 1 一维数组传参 #include <stdio.h> void test(int arr[])//ok? {} void test(int arr[10])//ok? {} void test(int* arr)//ok? {} void test2(int* arr[20])…...

Tuple 元组

文章目录 一、什么是元组 &#xff1f;二、元组的具体操作2.1 创建元组2.1.1 tuple() 创建元组函数和 list() 创建列表函数总结 2.2 元组的元素访问操作2.3 元组的元素计数操作2.4 zip 对象 一、什么是元组 &#xff1f; 列表属于可变序列,可以任意修改列表中的元素。 元组的…...

(资料收藏)王阳明传《知行合一》共74讲,王阳明知行合一音频讲解资料

今天给大家带来的不是软件&#xff0c;而是一份精神食粮——《知行合一》的教程福利。这可不是一般的教程&#xff0c;它关乎心灵&#xff0c;关乎智慧&#xff0c;关乎我们如何在纷繁复杂的世界中找到自己的位置。 咱们得聊聊王阳明&#xff0c;这位明代的大儒&#xff0c;他…...

空气质量预报模式系统WRF-CMAQ

空气污染问题日益受到各级政府以及社会公众的高度重视&#xff0c;从实时的数据监测公布到空气质量数值预报及预报产品的发布&#xff0c;我国在空气质量监测和预报方面取得了一定进展。随着计算机技术的高速发展、空气污染监测手段的提高和人们对大气物理化学过程认识的深入&a…...

Collections.sort()方法总结

Collections.sort()方法总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨 Java 中的 Collections.sort() 方法。这个方法是 Java 集合框架中的…...

Java23种设计模式(二)

1、单例模式 单例模式&#xff08;Singleton Pattern&#xff09;是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类&#xff0c;该类负责创建自己的对象&#xff0c;同时确保只有…...

Web前端收入来源:探索多元化的盈利渠道

Web前端收入来源&#xff1a;探索多元化的盈利渠道 在数字化时代&#xff0c;Web前端技术日益成为推动互联网业务发展的重要力量。对于前端开发者而言&#xff0c;除了传统的薪资收入外&#xff0c;还存在多种潜在的收入来源。本文将从四个方面、五个方面、六个方面和七个方面…...

抽象工厂模式(大话设计模式)C/C++版本

抽象工厂模式 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15927110.html #include <iostream> using namespace std;// 抽象产品Department ,定义具体产品的公共接口 class Department { public:virtual ~Department() default;virtual void Insert()…...

springboot宠物医院信息管理系统-计算机毕业设计源码04164

摘 要 现如今在中国&#xff0c;随着人民生活质量的逐渐提高&#xff0c;以及人民群众消费能力的日渐增长&#xff0c;各种各样的家养小动物&#xff0c;已经逐渐成为人类越来越亲密的生活伴侣。并且&#xff0c;现如今社会竞争及其激烈&#xff0c;人们的生活节奏越发急促、紧…...

Leetcode Hot100之哈希表

1. 两数之和 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现思路…...

Vision Transformer with Sparse Scan Prior

摘要 https://arxiv.org/pdf/2405.13335v1 In recent years, Transformers have achieved remarkable progress in computer vision tasks. However, their global modeling often comes with substantial computational overhead, in stark contrast to the human eye’s eff…...

笔记-python 中BeautifulSoup入门

在前面的例子用&#xff0c;我用了BeautifulSoup来从58同城抓取了手机维修的店铺信息&#xff0c;这个库使用起来的确是很方便的。本文是BeautifulSoup 的一个详细的介绍&#xff0c;算是入门把。文档地址&#xff1a;http://www.crummy.com/software/BeautifulSoup/bs4/doc/ …...

Tomcat Websocket应用实例研究

概述 本文介绍了如何根据Tomcat给出的websocket实例&#xff0c;通过对实例的学习&#xff0c;定制自己基于websocket的应用。 环境及版本&#xff1a; Ubuntu 22.04.4 LTSApache Tomcat/10.1.20openjdk 11.0.23 2024-04-16浏览器&#xff1a;Chrome 相关资源及链接 Class…...

leetcode-11-二叉树前中后序遍历以及层次遍历

一、递归版 前序遍历 &#xff08;先根遍历&#xff09; 中左右 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result new ArrayList<Integer>();preorder(root, result);return result;}public void preorder…...

Python基础学习笔记(十一)——集合

目录 一、集合的介绍与创建二、集合的存储原理三、元素的修改1. 添加元素2. 删除元素 四、集合的运算五、集合的判定 一、集合的介绍与创建 集合&#xff08;set&#xff09;&#xff0c;一种可变、无序、不重复的数据结构&#xff0c;由大括号{}内、用逗号分隔的一组元素组成。…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...