Python意想不到的表现:Brute Force vs Dictionaries(Collat​​z Sequence)

时间:2015-08-31 13:48:16

标签: python performance dictionary brute-force

在此问题中字典是否可能比Brute Force慢?

  • 问题(来自Project-Euler):

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

    n → n/2 (n is even)

    n → 3n + 1 (n is odd)

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

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

    可以看出,该序列(从13开始,在1结束)包含10个术语。虽然尚未证实(Collat​​z问题),但据认为所有起始数字都以1结束。

    哪个起始编号低于一百万,产生最长链?

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

  • 代码[暴力]:

    我开始使用一个强力程序,它从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
    

    然后我说:“太多时间了!让我们实施字典!”

  • 代码[字典]:

    使用词典,每次链结束时,链的起始编号和链片编号都存储在字典中,因此当它找到相同的编号超过一次时,它可以使用与此编号关联的值存储在字典中。

    5分钟后我停了下来。

    # 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 个答案:

答案 0 :(得分:1)

if str(k) in dictionary.keys():
#                      ^^^^^

很糟糕。这会将一组键变为list!并扫描lineraly(在python3中,它是一个生成器,但几乎同样糟糕)。

你可以说。

if str(k) in dictionary:

这是正确的,在O(1)而不是O(n)!

此外,在python中将事物转换为字符串以将其用作dict中的键是不必要的。数字很​​好,所以你可以说:k你现在所说的str(k)