python实现约瑟夫环时间复杂度计算_约瑟夫环问题解决方法时间复杂度分析

写这篇博客的起因是在牛客上刷到了一道约瑟夫环相关的题。牛客链接

在牛客上跑通过了,本着追求机器效率的原则,去leetcode上找到了同样的题,再跑了一遍,发现超时。看了几篇博客并思索许久后打算写这篇博客来探究

约瑟夫环问题在选取不同数据结构和不同处理方法的时候时间复杂度的优劣。leetcode链接

关于约瑟夫环及其递推公式请见:https://blog.csdn.net/u011500062/article/details/72855826

需要解释的是为什么受害者之前位置的人在下一轮的下标是(当前下标 - m)% 当前一轮的人数

分析时间复杂度:

如果要去直接模拟约瑟夫问题的各个环节的话,因为每次都要报数报m次,不考虑具体是什么数据结构实现存储,n个人需要报 n - 1次数,那么问题规模是O(n * m)

考虑具体使用的数据结构,比如数组,0号位代表一号人,1号位代表二号人,以此类推,那么有两种方法:

1.每当有一个人遇害,就把这个人从数组中删去,并且将此人后面的人向前移动。

2.只是把遇害者的位置标记,不删除该位置,之后访问的时候检查到某个位置的值之前标记过的话就跳过(没有人在这个位置上)

第一种情况,总共要挪动多少人 具体是难以推测的,因为每次都是以m为位移在当前数组上找下一个位置,但是可以假设最坏情况,每次移动的人数是当前数组人数 - 1

那么总的移动次数是 : (n - 1) + (n - 2) + (n - 3) + ...... + 1 = (n - 1) * n / 2 , 是 O(n ^ 2)级的。

第二种情况,属于暴力遍历,如果路途中没有遇到之前的遇害者位置,那么访问次数是 m,但是每有一个人遇害,遇害者位置就会 + 1, 所以每次的遍历次数 > m,越遍历下去情况越糟糕,因为人死得越来越多,需要访问-跳过的槽位也越来越多。总次数  > n * m

用Java实现:

其实第一种情况,对应于使用ArrayList,因为他的底层实现就是数组,并且每次删除元素都会把后面的元素平移。

第二种情况,没有什么类似的ADT实现,但是LinkedList有类似之处,LinkedList不能像ArrayList那样直接通过下标找到元素,而是需要一个节点一个节点地next来获取某个

下标位置的元素

至于公式推导法......因为是从 2 到 n 遍历,相当于线性时间复杂度 O (n),真的是数学可以造成降维打击......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值