文章目录

  • 问题描述
  • 思路
  • 代码实现

问题描述

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. 约瑟夫环 -- 丢手绢问题

    问题描述 约瑟夫环问题,也称为"丢手绢问题". 编号为 1-N 的 N 个士兵围坐在一起形成一个圆圈,从编号为 1 的士兵开始依次报数(1,2,3-这样依次报),数到 m 的 士兵 ...

  2. Algorithm One Day One -- 约瑟夫环(丢手绢问题)

    算法是编程的灵魂,是编程思想的精髓----Algorithm One Day One /******************************************************** ...

  3. Java中使用链表解决约瑟夫问题(丢手绢问题)

    文章目录 文章目录 前言 一.思路分析 二.代码实现 1.Chird类建立 2.链表创建 3.功能实现 总结 其他解决方式: Java中使用list解决约瑟夫问题https://blog.csdn.n ...

  4. 数据结构与算法: 约瑟夫问题(丢手绢)

    数据结构与算法: 约瑟夫(丢手绢)问题(单向链表,双向链表解决) Tips: 采用java语言, 关注博主,底部附有完整代码 采用到的知识点: 单向环形链表 双向环形链表 单向 / 双向 环形链表出圈 ...

  5. Java中使用list解决约瑟夫问题(丢手绢问题)

    文章目录 文章目录 前言 一.思路分析 二.代码实现 总结 其他解决方式: Java中使用环形链表解决约瑟夫问题https://blog.csdn.net/qq_35813811/article/de ...

  6. C语言||约瑟夫问题(丢手绢问题)

    20518 用时:1h 编程数组或指针实现约瑟夫环问题. 题目为:编号为1,2- n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺 ...

  7. 约瑟夫问题(丢手绢问题)

    问题复述:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自 ...

  8. 数据结构与算法--我们来玩丢手绢(约瑟夫环问题)

    我们来玩丢手绢 昨天我们打扑克,今天我们丢手绢 丢手绢我们都知道这个游戏,他的由来由约瑟夫 (Josephus)提出来的 据说著名犹太历史学家Josephus有过以下的故事:在罗马人占领乔塔帕特后,3 ...

  9. C++约瑟夫环(又称丢手绢)解决---最简单的理解

    首先约瑟夫环的定义: 在一间房间总共有n个人(下标0-n-1),只能有最后一个人活命. 按照如下规则去排除人: 所有人围成一圈, 从0开始 顺时针报数, 每次报到m的人将被排除掉 被排除掉的人将从房间 ...

  10. 1875 丢手绢 约瑟夫环变形 枚举

    1875 丢手绢 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 六一儿童节到了,小朋友们在玩丢手绢的游戏.总共有C个小朋友,编号从1到C,他们站成一个 ...

最新文章

  1. SQL基础---SQL WHERE 子句
  2. 【Linux】一步一步学Linux——dpkg-split命令(274)
  3. Python可以这样学(第五季:Socket编程)-董付国-专题视频课程
  4. error: component 'clippy' for target 'x86_64-unknown-linux-gnu' is unavailable for download 解决办法
  5. cad查看_CAD查看:Geometric Glovius Pro v5.1.0
  6. javascript 倒计时插件
  7. 微信公众号卡券php开发,微信公众号实现会员卡领取功能
  8. html5开发app的视频教程及相关资料
  9. 自然语言处理NLPIR-ICTCLAS 授权文件过期问题
  10. Java for Web学习笔记(六七):Service和Repository(2)抽象分层例子
  11. Unity文档——AssetBundle使用模式
  12. [答疑]类图:支付手段和优惠券、金额、积分有关
  13. c语言设计篮球计分器软件,会玩篮球更会玩篮球赛计时计分器,完整设计资料开源...
  14. 联合会杯-内马尔破门锋霸2球 巴西3-0西班牙3连冠
  15. Hibernate基于主键一对一映射操作实例
  16. PIC18F2455/2550/4455/4550之通用串行总线USB
  17. 六轴机械手程序 用信捷XD5和威纶触摸屏编写
  18. Android Apk加壳技术实战详解
  19. 线性代数及矩阵论(十一)
  20. 西交大计算机英语复试,西安交大复试的详细流程

热门文章

  1. java中软填空面试题,通过这9个Java面试题,就可以入职华为啦
  2. 大连理工优化方法matlab,大连理工大学2016年秋季优化方法大作业.pdf
  3. debian执行php网页,如何在Debian上安装和使用PHP Composer
  4. ubuntu 修改用户名和计算机名称
  5. 职场上个人的核心技术_职场上,这3种人表面老实,实际却是个“高手”,要远离...
  6. vue打包代码反编译_Android逆向反编译代码注入APK过程思路分析
  7. 【转】TcpListener和tcpclient使用
  8. 【转】3.4(译)构建Async同步基元,Part 4 AsyncBarrier
  9. 【读书笔记】.Net并行编程高级教程--Parallel
  10. Linq to SQL之使用事务