约瑟夫环的递归思想解

约瑟夫环递归算法详解与实现 迭代算法通过循环来模拟报数和淘汰的过程,避免了递归调用的额外开销,并在实际应用中通常具有更好的性能表现。约瑟夫环问题是一个著名的理论问题,其背景是在古罗马时期,有n个犯人被围成一个圈,从第一个人开始报数,每次报到m的人将被处决,然后从下一个人开始重新报数,直到所有人都被处决。有n个人围成一圈,从第一个人开始报数,每次报到m的人将被淘汰出局,然后从下一个人开始重新报数,直到最后只剩一个人为止。假设我们知道在n-1个人中,谁是幸运者(即他在子问题中的序号),那么我们可以通过这个信息来找出在n个人中谁是幸运者。 阅读详情

原文地址:http://blog.youkuaiyun.com/u014613043/article/details/50905475

今天做约瑟夫环的题目,对于递归解法不太了解。在网上找了一篇比较好理解的文章。

本文为学习《剑指offer》的记录。因其原理在原作者博客上找不到,所以,只能自己编写记录,如有不当之处,欢迎指正。

题目描述: 
n个数,编号为 0 , 1, ……, n-1 排成一个圆圈,从数字 0 开始,每次从这个圆圈中删除第 m 个数,请问最后一个剩下的数是多少?

推导过程 
定义一个函数 f(n, m) 为 n 个数中取 m 最后剩下的编号。 
第一个被删除的数是 (m-1)%n, 记为 k 。此时因为序列已经不连续,函数可以定义为 f’ ( n-1, m) 。 
明显,最后剩下的编号相等,于是: f(n,m) = f’(n-1, m)

然后我们对剩下的数做一个简单的映射:

k+1 –> 0 
k+2 –> 1 
. 
. 
n-1 –> n-k-2 
0 –> n-k-1 
1 –> n-k 
. 
. 
k-1 –> n-2

这个映射可以记为 
p(x) = (x-k-1)%n 
其中 x 为映射前的数 (可以自己推导一下)

那么逆映射就是: 
p-1(x) = (x + k + 1 ) %n 
(还是建议自己推导一下)

那么,对于上面的函数 f’(n-1, m),就有 
f’(n-1, m) = p-1[f(n-1, m)] = [f(n-1, m) + k +1]%n = f(n, m)

将 k= (m-1)%n 代入: 
f(n, m) = [f(n-1, m) + m]%n

这就是我们要的通项公式。 
很明显,当 n = 1 时,f = 0; 
于是:

f(n, m) = 0, n = 1 
f(n, m) = [f(n-1, m) + m]%n, n>1

使用循环就可以轻松解决这个问题了。

–END–



下面是我的代码:

#include <stdio.h>
#include <string.h>
#define M 10
int a[M] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int n = 0;
void swap(int *a, int *b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}
void fun1()
{
int number = M;
int xianyou  = number;
int i = 0;
int count = 1;
while(number != 0)
{
if (i > number)
{
i = i % xianyou;
}
if (a[i] != 0)
{
if (count == n)
{
printf("%d ", a[i]);
a[i] = 0;
count = 1;
i++;
number--;
}
else
{
i++;
count++;
}
}
else
{
i++;
}
}
}
int fun2(int a, int b)
{
if (a == 1)
{
return 0;
}
else
{
return ((fun2(a - 1, b) + b) % a);
}
}
int main(int argc, char const *argv[])
{
printf("Please input num :\n");
scanf("%d", &n);
int count = 1;
int m = M;
/*while(a[0] != 0)
{
for (int i = 0; a[i] != 0; ++i, ++count)
{
if (count == n)
{
printf("%d ", a[i]);
a[i] = 0;
for (int j = i; j < M; ++j)
{
swap(&a[i], &a[i + 1]);
}
}
}
}*/
// fun1();
printf("%d\n", fun2(m, n) + 1);
return 0;
}

Java之约瑟夫环问题 通过学习Java约瑟夫环问题,理解大问题拆解成小问题,然后小问题之间递推求解,这也是动态规划的核心思想。 阅读详情

相关推荐

Java后端开发实战:手把手教你用e签宝API搞定电子合同签署(附完整代码)

本文详细解析了Java后端开发中如何通过e签宝API实现电子合同签署的全流程,包括环境配置、核心架构设计、Token管理、签署流程实现及回调处理等关键环节。通过完整的代码示例和最佳实践,帮助开发者高效集成电子签名服务,提升企业数字化转型效率。

weixin_42662293的博客 532

约瑟夫环(数组和递归)

printf("请输入人数(1-100):");printf("请输入报数:");int i;for(i=1;i

RVETHR的博客 2079

手把手教你学Simulink——机器人力控场景实例:基于Simulink的永磁同步电机重力补偿力矩控制仿真

本文介绍了基于Simulink的机器人重力补偿力矩控制仿真方法。针对机器人悬停时电机发热、抖动等问题,提出通过前馈补偿重力转矩的解决方案。文章详细阐述了从机器人动力学建模、重力补偿计算、PMSM转矩控制到系统集成的完整实现流程,并以2-DOF机械臂为例验证了补偿效果。结果表明,重力补偿能显著降低电机电流和拖拽力,提高系统柔顺性。文中还提供了高级功能扩展方向,如参数辨识、摩擦补偿等,为实际工程应用提供了参考框架。

MHD0815的博客 154

关于约瑟夫环的递归思路

有n个人,编号为1~n,从第一个人开始报数,从1开始报,报到m的人会死掉,然后从第m+1个人开始,重复以上过程。在死了n-1个人后,问最后一个人的编号是? 解法一模拟: 采取一个dead[]数组,每次从一个没有死的人开始,活着的人依次报数(那么需要跳过dead[i]==true的人),到m处那个人去世 同时计数num++ 当杀死num==n-1时,返回dead[]数组中为false的人下标+1 易错点(下标) 解法二递归: 将n个人排开,第m个人奖去世=》子问...

一只老风铃 598

Python 爬虫实战:爬取电商平台商品信息(价格 / 销量 / 评价)

摘要:本文详细介绍基于Python的电商商品信息爬取技术方案,以京东商品详情页为例,对比分析静态(BeautifulSoup)和动态(Selenium)两种爬取方式的实现逻辑。静态爬取适合获取基础信息,而动态爬取可解决JS渲染数据的获取问题。文章包含完整的代码实现、反爬规避策略及数据存储方案,涵盖商品名称、价格、销量、评价等核心数据提取。同时强调爬虫的合规使用,提供扩展方向建议,为电商数据采集提供实用技术参考。

2503_91057718的博客 2024

手把手教你学Simulink--双足机器人的反步控制方法仿真

本文介绍了在Simulink中基于反步控制方法进行双足机器人仿真研究的步骤。主要内容包括:1)准备工作,包括MATLAB/Simulink安装和相关工具箱配置;2)构建简化双足机器人模型;3)设计反步控制器,阐述其递归设计原理及Lyapunov函数构造方法;4)通过MATLAB Function块实现控制逻辑并连接模型;5)仿真参数配置和结果分析。文章强调反步控制适用于非线性系统,通过逐步构造虚拟控制律保证系统稳定性,并指出需要多次调试和查阅文献来优化控制效果。该教程为研究双足机器人运动控制提供了实用的仿真

MHD0815的博客 153

约瑟夫环问题——递归解决

问题: 约瑟夫,是一个古犹太人,曾经在一次罗马叛乱中担任将军,后来战败,他和朋友及另外39个人躲在一口井里,但还是被发现了。罗马人表示只要投降就不死,约瑟夫想投降,可是其他人坚决不同意。怎么办呢,他想到一个主意: 让41个人围成一个圆圈,从第一个人开始报数,数到3的那个人被旁边的人杀死。这样就可以避免自杀了,因为犹太人的信仰是禁止自杀的。结果一群人杀来杀去最后只剩下两个了,就是约瑟夫和他朋友,于...

qq_38596491的博客 3180

基于ZYNQ PL的AD7606数据采集与FFT实时频谱分析:从硬件到创新实现

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKnmpgJm-1750295287594)(https://example.com/fft_plot.png)]本文涉及代码已在Xilinx ZCU102开发板与AD7606评估板上验证通过,采样率支持200KSPS@8通道,FFT计算延迟<1ms。传统MCU+DSP方案难以兼顾速度与功耗,而ZYNQ的PL+PS架构为这一问题提供了完美解决方案。本文实现的ZYNQ PL方案突破了传统处理器的性能瓶颈,通过。

QQ_778132974的博客 339

约瑟夫环问题——一般解+数学模型递归解

约瑟夫环问题集合形式成环逻辑。约瑟夫问题是个有名的问题:N个人围成一圈,每个人都有自己对应的号数(号数从1到N),从1号开始报数(报数从数字1开始,轮到下一个人数字递增),当有人报数的数字为M将会被杀掉,下一个人接着从数字1开始报数,循环多次直到最后只剩下一个人,其余人都将被杀掉。如图所示,M为步长,先减掉6个人(arrayList.size()-left),在对8求余数,就等于2,表示杀集合中第2个,转换成下标2-1赋值给变量index,remove(index)。

Gojavaee的博客 2067

Python 爬虫实战:爬取评论数据做情感分析

摘要:本文介绍基于Python的京东商品评论爬取与情感分析全流程实现。通过Requests库抓取评论数据接口,结合JSON解析获取结构化评论信息。利用SnowNLP进行中文文本情感分析,量化用户评价的情感倾向(正面/负面/中性)。结果显示正面评论占比66.3%,负面评论13.3%,关键词分析发现"卡顿""发热"是主要负面因素。该方法可应用于产品优化、品牌管理等场景,为决策提供数据支持。

2503_91057718的博客 1709

基于四旋翼模型的火箭型无人机视线角保持控制仿真设计

本文针对火箭型无人机的视线角保持控制问题展开研究。基于四旋翼动力学模型,通过改造设计了一种摄像头朝上安装的特殊无人机系统,用于追踪空中目标。文章详细推导了坐标系定义、运动学和动力学方程,重点分析了摄像头安装与视线几何关系,建立了目标运动模型和视线向量计算方法。通过解算期望姿态角,实现了使机体Z轴始终对准目标的控制目标。仿真结果表明,该系统能有效完成视线角保持任务,为空对空监视等应用场景提供了可行方案。~~~~~

huanghm88的专栏 143

约瑟夫环递归算法(C++)(初学者也能看懂逻辑分析)

题目: n个人围成一圈(编号从1到n),从第1个人开始报数,报到m的人出列,从下一个人再重新报数,报到m的人出列,如此下去,直至所有人都出列。求最后一个出列的人的编号。 先给出核心代码: #include &lt;iostream&gt; using namespace std; int josephus(int n, int m) { if(n == 1) return 0; else r...

Chilan_Yuk的博客 2128

Linux 内核中 ARP 协议的全链路解析:从触发机制到物理层发送

核心设计思想按需解析:减少不必要的 ARP 请求,降低网络负载。分层解耦:协议栈各层(邻居子系统、Netfilter、驱动)职责分离,提高扩展性。ARP的核心作用是将IP映射为MAC地址,确保数据链路层能正确封装帧。其触发时机围绕“未知MAC地址需求”展开,覆盖通信初始化、缓存更新、网络变更及维护等多种场景。

数字人生 367

算法之解“约瑟夫环”(递归思想)

题目 一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到M,凡报到M的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王? 输入格式: 输入在一行中给两个正整数N, M(1<= N,M ≤10000000)。 输出格式: 在一行中输出当选猴王...

shanjixin的博客 1241

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

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

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

390. Elimination Game(约瑟夫环)

There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other number afterward until you reach the end of the list. Repeat the previous step agai...

katrina95的博客 190

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

约瑟夫问题

问题提出: n个人(编号1~n)围成一个圈,从1开始依次报数,报到m的出列,剩下的人继续从1开始报数(由刚出列的人的下一个人开始)。求最后出列的人(胜利者)的编号。 为了讨论方便,先把问题稍微改变一下,并不影响原意: 问题描述:n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。求胜利者的编号。 我们知道第一个人(编号一定是m%n-1) 出列之后,剩...

weixin_33725126的博客 108

约瑟夫环问题映射关系的推导

关于约瑟夫环问题的解题方法可参考:         http://www.cnblogs.com/woodfish1988/archive/2007/02/18/652251.html。        http://blog.163.com/elite_lcf/blog/static/678395382009931105328270/      本文着重介绍用递归思想解题时,映射关系的推

zhanshenwu的专栏 857

约瑟夫环-递归分析数学解法(详细分析)-C/C++系列

SITUATION-约瑟夫环问题描述 已知n个人围成一圈(编号:1,2,3,…,n),从编号为1的人开始报数,报数为m的那个人出列;从他的下一个人又从1开始数,同样报数为m的人出列;依此循环下去,直到剩余一个人。求最后这一个人在最开始的序列中编号是几号? ACTION-递归求解法 将这n个人从0~n-1编号(1是习惯从0开始;2是如果m大于等于n时,第一个出列的人编号是m%n,m%n可能等于0,简...

AngongYY的博客 1万+

递归算法解约瑟夫环

约瑟夫环问题介绍:17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。 这里我们简化一下问题,假设共10个人,每数到4就将第四个人...

zzwjames的博客 800

约瑟夫环之二(用递归的思想解决Josephus问题)

原来写过一篇关于约瑟夫问题的链表实现解法 ,刷九度题到http://ac.jobdu.com/problem.php?pid=1356 时,再次遇到这个问题,记下用递归思想解决约瑟夫问题的方法: 初始情况: 0, 1, 2 ......n-2, n-1 (共n个人) 第一个人(编号一定是(m-1)%n,设之为(k-1) ,读者可以分m=n的情况分别试下,就可以得出结论) 出列之后,剩下的n-1

wusuopuBUPT的专栏 2万+

Py递归算法解“约瑟夫环”的一种变形问题

Py递归算法 解“约瑟夫环” (“约瑟夫环”的一种变形问题) 题目: 约瑟夫环的一种变形。我们考虑的问题是开始时有n个人,记为1到n,站成一个圆圈。每一步,每第2个人将被去除,直到只剩下一个人为止。我们把剩下的人记为J(n),用程序求出1≤n≤16的J(n)(“约瑟夫环”点此跳转百科词条) 思路解析:   根据题意,要把人依序站队,数据结构选择数组(list)最为合适,用整数1~n来标识队列中人的初始站队位置。要让队列像贪吃蛇一样首尾相接成为圆圈,依list特性借助了list的pop和app

m0_57158496的博客 1389

约瑟夫环问题(简单解法和递归解法)(python)

约瑟夫环问题的简单解法和递归解法简单解法使用双向队列(deque) 函数使用列表加指针双层遍历递归解法 相关题:剑指offer 46 - 孩子们的游戏 简单解法 思路:刚开始把所有的人放到一个列表里面去,报的数字不是k就把这个人放到列表的最后一个位置上面去,如果是k就把这个数字从列表中去掉,直到列表剩下1个人为止。 使用双向队列(deque) 函数 deque函数简介 from collections import deque #deque是一种双向队列,底层据说也是同样用双链表实现的 deque.r

王叔叔 2872

C++ - 8月31日 - 两种方法解决约瑟夫环问题(数组、递归)

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3,...n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出圈,他的下一个人又从1开始报数,数到m的那个人又出圈;按照这个规律一直重复下去,知道剩余最后一个胜利者。..................

曾铎的博客 7370

约瑟夫环递归写法

约瑟夫环 递归 写法

m0_37971327的博客 2547

约瑟夫环--通俗易懂的巧解

0x01.问题 N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。求幸存者的编号。 0x02.详细分析 约瑟夫环最容易想到的就是模拟,可以普通的用数组模拟,也可以用循环链表,用数组模拟的代码如下: int lastRemaining(int n, int m) { vector<int> base(n, 1); m=m%n; in...

ATFWUS的博客 2190

约瑟夫环java分析_利用递归思想解决约瑟夫环问题(Java 描述)

先看下在10人成环,逢四去一的情况下,对问题的分析:10个人手拉手围成一圈,由第一个位置(index = 0)开始报数,数到 4 的人被 kick 出圈外,每次kick一个人,重新编号,又从 index = 0的位置报数,以此向下类推: 新环是由(旧环中编号 - 最大报数值)% 旧总人数 得到的,所以逆推时可以由(新环中的数字 + 最大报数值)% 旧总人数 取得。即 old_number =...

weixin_34296646的博客 544
上一篇: 年份信息查询程序
下一篇: 矩阵乘法的C语言实现
sevanco
博客等级 码龄12年 4粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值