Python出人意料的性能:蛮力vs字典(Collatz序列)

Python出人意料的性能:蛮力vs字典(Collatz序列),python,performance,dictionary,brute-force,Python,Performance,Dictionary,Brute Force,在这个问题上,字典可能比暴力慢吗? 问题(来源): 为正整数集定义以下迭代序列: n→ n/2(n为偶数) n→ 3n+1(n为奇数) 使用上述规则并从13开始,我们生成以下序列: 13→ 40→ 20→ 10→ 5.→ 16→ 8.→ 4.→ 2.→ 1 可以看出,这个序列(从13开始到1结束)包含10个术语。虽然还没有被证明(科拉兹问题),但人们认为所有的起始数字都以1结束 100万以下的哪个起始编号产生的链最长? 注:一旦链开始,条款允许超过一百万 代码[暴力]: 我从一个蛮力程序开始,

在这个问题上,字典可能比暴力慢吗?

  • 问题(来源):

    为正整数集定义以下迭代序列:

    n→ n/2(n为偶数)

    n→ 3n+1(n为奇数)

    使用上述规则并从13开始,我们生成以下序列:

    13→ 40→ 20→ 10→ 5.→ 16→ 8.→ 4.→ 2.→ 1

    可以看出,这个序列(从13开始到1结束)包含10个术语。虽然还没有被证明(科拉兹问题),但人们认为所有的起始数字都以1结束

    100万以下的哪个起始编号产生的链最长?

    注:一旦链开始,条款允许超过一百万

  • 代码[暴力]:

    我从一个蛮力程序开始,该程序从1到1000000取每个数字,并打印找到的最长链

    完成大约需要30秒。

    # number from 1 to 1000000
    num = 0
    
    # longest chain here
    maxLength = 0
    
    # number that produce the longest chain
    result = 0
    
    while num < 1000000:
        num += 1
        k = num
    
        # count the current chain pieces
        i = 0
    
        while k > 1:
            i += 1
            if k%2 == 0:
                k /= 2
            else:
                k = k*3 + 1
    
        if maxLength < i:
            maxLength = i
            result = num
    
    print result
    
    # number from 1 to 1000000
    num = 0
    
    # longest chain here
    maxLength = 0
    
    # number that produce the longest chain
    result = 0
    
    dictionary = {}
    
    while num < 1000000:
        num += 1
        k = num
        i = 0
        while k > 1:
            # if it processed the number before, it use the shortcut
            if str(k) in dictionary.keys():
                i += dictionary[str(k)]
                break
    
            i += 1
            if k%2 == 0:
                k /= 2
            else:
                k = k*3 + 1
    
        # add new shortcut
        if not (str(num) in dictionary.keys()):
            dictionary[str(num)] = i
    
        if maxLength < i:
            maxLength = i
            result = num
    
    print result
    
    #从1到1000000的数字
    num=0
    #这里最长的链条
    maxLength=0
    #产生最长链的编号
    结果=0
    当num<1000000时:
    num+=1
    k=num
    #计算当前链件的数量
    i=0
    当k>1时:
    i+=1
    如果k%2==0:
    k/=2
    其他:
    k=k*3+1
    如果maxLength
    然后我说:“时间太多了!让我们实现字典吧!”

  • 代码[字典]:

    对于字典,每次链结束时,链的起始编号和链件编号都存储在字典中,因此当它多次找到相同的编号时,可以使用字典中存储的与此编号关联的值

    5分钟后,我停止了它。

    # number from 1 to 1000000
    num = 0
    
    # longest chain here
    maxLength = 0
    
    # number that produce the longest chain
    result = 0
    
    while num < 1000000:
        num += 1
        k = num
    
        # count the current chain pieces
        i = 0
    
        while k > 1:
            i += 1
            if k%2 == 0:
                k /= 2
            else:
                k = k*3 + 1
    
        if maxLength < i:
            maxLength = i
            result = num
    
    print result
    
    # number from 1 to 1000000
    num = 0
    
    # longest chain here
    maxLength = 0
    
    # number that produce the longest chain
    result = 0
    
    dictionary = {}
    
    while num < 1000000:
        num += 1
        k = num
        i = 0
        while k > 1:
            # if it processed the number before, it use the shortcut
            if str(k) in dictionary.keys():
                i += dictionary[str(k)]
                break
    
            i += 1
            if k%2 == 0:
                k /= 2
            else:
                k = k*3 + 1
    
        # add new shortcut
        if not (str(num) in dictionary.keys()):
            dictionary[str(num)] = i
    
        if maxLength < i:
            maxLength = i
            result = num
    
    print result
    
    #从1到1000000的数字
    num=0
    #这里最长的链条
    maxLength=0
    #产生最长链的编号
    结果=0
    字典={}
    当num<1000000时:
    num+=1
    k=num
    i=0
    当k>1时:
    #如果之前处理过该号码,则使用快捷方式
    如果dictionary.keys()中的str(k):
    i+=字典[str(k)]
    打破
    i+=1
    如果k%2==0:
    k/=2
    其他:
    k=k*3+1
    #添加新快捷方式
    如果不是(dictionary.keys()中的str(num)):
    字典[str(num)]=i
    如果maxLength
字典是否可能会影响此程序的性能,使其变得非常缓慢?它们不是用来提高性能和加速程序吗?或者。。。我的代码有问题吗

谢谢

这个

if str(k) in dictionary.keys():
#                      ^^^^^
这很糟糕。这将把一组键变成一个
列表
!并扫描该线路(在python3中,它是一个发生器,但几乎同样糟糕)

你可以说

if str(k) in dictionary:
这样做是正确的,用O(1)代替O(n)


此外,在python中,将内容转换为字符串以用作
dict
中的键是不必要的。数字很好,所以你真的可以说:
k
无论你现在说什么
str(k)

,只要你纠正一下,现在只需要2.5秒!谢谢