本文主要是介绍圆圈报数-约瑟夫问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
问题概述
约瑟夫问题:n个人围成一圈,从第一个人开始报数,数到m的人出圈;再由下一个人开始报数,数到m的人出圈;…输出依次出圈的人的编号。n,m由键盘输入。
解题思路
1 初始级算法
循环报数,每次数到m的倍数就出局此时指向的人。
可以通过list或者是指针来实现保存当前还在游戏中的人的功能,通过索引去出局人。
但是这样的算法效率很低,基本上要O(m*n)的时间复杂度。
2优化算法
不需要通过循环报数,循环中很多步骤都是浪费的,如果当前游戏中还有n1个人,
如果给这个n1个人编号 从1到n1
那么下一次出局的人会是编号 (m+n1-1)%n1+1 或者简化为(m-1)%n1+1
通过这样的优化可以快速找到每一轮需要出局的人,这种情况下如list来存储当前还在游戏中的人的功能就会存在一定的优势。最后时间复杂度为O(n)
3动态规划算法
反思之前为什么要用额外的空间保存当前还在游戏中的人,那就是因为每一轮游戏结束之后部分人的索引改变了,如下
如果当前游戏还有n个人,从1到n进行编号,并且这一轮编号为a 的人出局了
原始: 1 2 3 … a-1 a a+1 …n
a出局之后: 1 2 3 … a-1 a+1 …n
编号a-1的人的下一位人的从n变为了n+1
而报数顺序变成了如下结构
a+1 a+2 …n 1 2 3 …a-1
如果我们按照这样的报数顺序对人重新编号,得到一个从1到n-1的数列,这个步骤相当于对原来人的编号进
这篇关于圆圈报数-约瑟夫问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!