Python 算法 :讨论计算3-n之间的最大素数与时间复杂度问题

一、指定一个数n,计算出3-n之间的最大素数,于是简单的实现一下,代码如下:

import datetime
def max_num(n):
    list1 = []
    list2 = []
    if type(n) is int:
        if n == 1:
            return '1 is 素数'
        if n == 2:
            return '2 is 素数'
        elif n > 2:
            for i in range(3, n+1):
                list1.clear()
                for j in range(1, i+1):
                    if i % j == 0:
                        list1.append(j)
                if len(list1) <= 2:
                    list2.append(i)
            return list2[-1]
    else:
        return False


if __name__ == "__main__":
    print(max_num(1))
    print(max_num(2))
    print(max_num(1000.01))
    print(datetime.datetime.now())
    print(max_num(30000))
    print(datetime.datetime.now())

执行后的结果:

二、现在我们传的n值是30000,也就是计算的是3-30000之间的最大素数,可是我们发现运算时间已经有37秒,如果n是30万呢,就会发现等了好久都不出结果,这时候就需要对实现的脚本进行优化了

我们发现,其他都没动,我只是在第一层的循环下面添加了一个判断。给定一个数n,那么3-n之间的偶数,一定不是素数。这样相当于只是执行了3-30000非偶数的子循环。时间由之前的37秒,变成了现在的20秒

三、我们继续优化它

 我又做了一下修改,第二层循环我只循环n的二分之一,这个是为什么呢?比如1 2 3 4 5 6 7 8 9 10,如果外层循环的n是10,那肯定是由1*10,2*5组成。如果外层循环n是1000,那肯定是由1*1000,2*500,3*333.33,4*250,5*200,随着左边1,2,3,4,i值的逐渐增大,右边的数会逐渐缩小,最后变成200*5,250*4,500*2,1000*1。而n=1*n本身,和n=n*1是任何数都满足的。所以从2开始,然后又是左右对称,所以,最后其实就是2*500,3*333.33,4*250,5*200,…i*(n/i)…,200*5,250*4,500*2最后公式缩减为2*(n/2),3*(n/3)……i*(n/i)……(n/2)*2,我们可以看到左侧值,最后是2,3,4,5……i…一直到…n的二分之一。所以我们二次循环的时候,选择从2开始到n的二分之一是肯定可以包含所有情况的。我们可以看到时间又缩短到了10秒

四、继续优化它,现在是两个嵌套循环,我们能不能拆分成二个单个循环?两个单个循环的时间复杂度要远远小于两个嵌套循环

这次我们计算到平方根,并且拆分循环。看一下成果,30万的量级,也就2秒钟就出来了结果。如果还用上面的几种方法,30万的数据,没有几个小时应该出不来数据。

import datetime
import math
def max_num(n):

    if type(n) is int:
        if n <= 2:
            print('1&2 都是素数')
        else:
            t = int(math.sqrt(n)+1)
            for i in range(2, t):
                if n % i == 0:
                    return 0
            return 1
    else:
        return False
if __name__ == "__main__":
    num_list = []
    print(datetime.datetime.now())
    for i in range(1, 300000+1):
        if max_num(i):
            num_list.append(i)
    print(num_list[-1])
    print(datetime.datetime.now())

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值