约瑟夫环(丢手绢问题)
文章目录
- 问题描述
- 思路
- 代码实现
问题描述
有 1~N
个数字,从 1~m
依次报数,数到 m
的数字要被删掉,求最后剩下的数字是?
思路
第一次报数 | 第二次报数 |
---|---|
1 | n-m+1 |
2 | n-m+2 |
… | … |
m-2 | n-2 |
m-1 | n-1 |
m | 被删掉了 |
m+1 | 1 |
m+2 | 2 |
… | … |
n-1 | n-1-m |
n | n-m |
通过上面的表格,我们可以发现这样的规律:
将某数字第一次报数设为 first
,第二次报数设为 second
。那么存在这样的关系:first=(second+m−1)%n+1first = (second + m - 1) \% n + 1first=(second+m−1)%n+1(公式一)
为什么不是 first=(second+m)%nfirst = (second + m) \% nfirst=(second+m)%n (公式二)呢?其实一开始我确实总结出来的是公式二,但是发现有个漏洞,数字编号是从 1
开始的,而公式二的编号是从 0
开始的,具体来说,就是当 second = n-m
时,first = 0
。可以看到并不符合实际,first=n
才对。换言之,也就是如果我们从 0
开始计数,那么公式二是可用的,如何从 0
开始计数呢? 答案就是把数字序列存到数组里嘛~
因此,将公式二可以进化为 first=(second+m)%n+1first = (second + m) \% n + 1first=(second+m)%n+1(公式三),但是简单的为公式二的结果 +1
,就导致在公式二中,本来只有 second = n-m
结果不符合实际,而在公式三中,变成了只有 second = n-m
的结果符合实际,原本没问题的都变得有问题了……这是因为我们没有做到加减均衡,只有 +1
,而没有 -1
。因此公式一应运而生~
那么我们可以得到这样的规律:
当n>1时,f(n)=(f(n−1)+m−1)%n+1当 n>1 时,f(n) = (f(n-1) + m - 1) \% n + 1当n>1时,f(n)=(f(n−1)+m−1)%n+1
当n=1时,f(1)=1当 n=1 时,f(1) = 1当n=1时,f(1)=1
解释一下就是,剩最后一个数的时候直接返回最后一次报数为 1
的数,反之则需要继续删除一个数。
而当 n-1=1
时,f(n)
也就意味着,最后一次报数为 1 的数,倒数第二次报数的时候它报的是几。
那么对于 f(n-1)
的调用也就意味着,本次报数为 n 的数,下一次报数为几。
说到这里已经很清楚了,显而易见的递归思想。
代码实现
int m;
int yuesefu(int n){if(n == 1) return 1; // 最后一次报数为 1,开始回溯return (yuesefu(n-1) + m - 1) % n + 1; // f(n-1)==1的时候开始回溯,求最后一次报数为 1 的数,第一次报数为几?
}// 还可以再简化
int m;
int yuesefu(int n){return n == 1 ? 1 : (yuesefu(n-1) + m - 1) % n + 1;
}// 如果将数字序列存入数组中,则可用公式二
int m;
int yuesefu(int n){return n == 0 ? 0 : (yuesefu(n-1) + m) % n;
}
约瑟夫环(丢手绢问题)相关推荐
- 约瑟夫环 -- 丢手绢问题
问题描述 约瑟夫环问题,也称为"丢手绢问题". 编号为 1-N 的 N 个士兵围坐在一起形成一个圆圈,从编号为 1 的士兵开始依次报数(1,2,3-这样依次报),数到 m 的 士兵 ...
- Algorithm One Day One -- 约瑟夫环(丢手绢问题)
算法是编程的灵魂,是编程思想的精髓----Algorithm One Day One /******************************************************** ...
- Java中使用链表解决约瑟夫问题(丢手绢问题)
文章目录 文章目录 前言 一.思路分析 二.代码实现 1.Chird类建立 2.链表创建 3.功能实现 总结 其他解决方式: Java中使用list解决约瑟夫问题https://blog.csdn.n ...
- 数据结构与算法: 约瑟夫问题(丢手绢)
数据结构与算法: 约瑟夫(丢手绢)问题(单向链表,双向链表解决) Tips: 采用java语言, 关注博主,底部附有完整代码 采用到的知识点: 单向环形链表 双向环形链表 单向 / 双向 环形链表出圈 ...
- Java中使用list解决约瑟夫问题(丢手绢问题)
文章目录 文章目录 前言 一.思路分析 二.代码实现 总结 其他解决方式: Java中使用环形链表解决约瑟夫问题https://blog.csdn.net/qq_35813811/article/de ...
- C语言||约瑟夫问题(丢手绢问题)
20518 用时:1h 编程数组或指针实现约瑟夫环问题. 题目为:编号为1,2- n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺 ...
- 约瑟夫问题(丢手绢问题)
问题复述:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自 ...
- 数据结构与算法--我们来玩丢手绢(约瑟夫环问题)
我们来玩丢手绢 昨天我们打扑克,今天我们丢手绢 丢手绢我们都知道这个游戏,他的由来由约瑟夫 (Josephus)提出来的 据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,3 ...
- C++约瑟夫环(又称丢手绢)解决---最简单的理解
首先约瑟夫环的定义: 在一间房间总共有n个人(下标0-n-1),只能有最后一个人活命. 按照如下规则去排除人: 所有人围成一圈, 从0开始 顺时针报数, 每次报到m的人将被排除掉 被排除掉的人将从房间 ...
- 1875 丢手绢 约瑟夫环变形 枚举
1875 丢手绢 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 六一儿童节到了,小朋友们在玩丢手绢的游戏.总共有C个小朋友,编号从1到C,他们站成一个 ...
最新文章
- SQL基础---SQL WHERE 子句
- 【Linux】一步一步学Linux——dpkg-split命令(274)
- Python可以这样学(第五季:Socket编程)-董付国-专题视频课程
- error: component 'clippy' for target 'x86_64-unknown-linux-gnu' is unavailable for download 解决办法
- cad查看_CAD查看:Geometric Glovius Pro v5.1.0
- javascript 倒计时插件
- 微信公众号卡券php开发,微信公众号实现会员卡领取功能
- html5开发app的视频教程及相关资料
- 自然语言处理NLPIR-ICTCLAS 授权文件过期问题
- Java for Web学习笔记(六七):Service和Repository(2)抽象分层例子
- Unity文档——AssetBundle使用模式
- [答疑]类图:支付手段和优惠券、金额、积分有关
- c语言设计篮球计分器软件,会玩篮球更会玩篮球赛计时计分器,完整设计资料开源...
- 联合会杯-内马尔破门锋霸2球 巴西3-0西班牙3连冠
- Hibernate基于主键一对一映射操作实例
- PIC18F2455/2550/4455/4550之通用串行总线USB
- 六轴机械手程序 用信捷XD5和威纶触摸屏编写
- Android Apk加壳技术实战详解
- 线性代数及矩阵论(十一)
- 西交大计算机英语复试,西安交大复试的详细流程
热门文章
- java中软填空面试题,通过这9个Java面试题,就可以入职华为啦
- 大连理工优化方法matlab,大连理工大学2016年秋季优化方法大作业.pdf
- debian执行php网页,如何在Debian上安装和使用PHP Composer
- ubuntu 修改用户名和计算机名称
- 职场上个人的核心技术_职场上,这3种人表面老实,实际却是个“高手”,要远离...
- vue打包代码反编译_Android逆向反编译代码注入APK过程思路分析
- 【转】TcpListener和tcpclient使用
- 【转】3.4(译)构建Async同步基元,Part 4 AsyncBarrier
- 【读书笔记】.Net并行编程高级教程--Parallel
- Linq to SQL之使用事务