当前位置: 首页 > 知识库问答 >
问题:

Python意想不到的性能:蛮力vs字典(Collatz Sequence)

刘运浩
2023-03-14

有没有可能字典在这个问题上比蛮力慢?

>

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

<代码>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

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

代码[词典]:

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

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

史烨
2023-03-14

这个

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

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

你可以说。

if str(k) in dictionary:

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

此外,在python中,将事物转换为字符串并将其用作dict中的键是不必要的。数字很好,所以您可以在当前所说的任何地方都说:k

 类似资料:
  • 我试图基于字母替换(没有固定偏移量)解密密码文本。我的目标是找到钥匙。 例如: 这是我的纯文本: 直到现代,密码学几乎只指加密,即将普通信息转换为无法理解的文本的过程 我生成一个随机替换,得到如下结果: 该公司的董事会成员在董事会会议上发言 规则: 纯文本只包含较低的字母a... z 空格不加密 英文文本 我想当我使用英文字母频率时,我可以用最常用的字母链接替换加密文本中最常用的字母:https:

  • 我是Python新手,刚刚开始尝试使用LeetCode来构建我的排骨。在这个经典问题上,我的代码遗漏了一个测试用例。 问题如下: 给定一个整数数组,返回两个数字的索引,使它们相加到一个特定的目标。 您可以假设每个输入都有一个精确的解决方案,并且您可以不使用相同的元素两次。 例子: 给定nums=[2,7,11,15],target=9, 因为Nums[0]Nums[1]=2 7=9,返回[0,1]

  • 对于我的Intro CS类,我们必须创建一个程序,找到一个特定的数字,在本例中是一个地址。地址在1000和9999之间,必须满足以下标准: 所有四位数字都不同 千位数字是十位数字的三倍 这个数字是奇数 数字之和是27 到目前为止,我已经能够生成数字的范围,并缩小奇数,但其余的是相当混乱的。建议?

  • 这个问题可能没有具体说明,但我认为很重要。当您想要解决一个优化问题而又不太熟悉方法时,首先想到的是它。 我可以举一些简单的例子: 获取列表的min元素(非常简单) 列出集合的所有置换 列出集合的所有子集 这些问题都有成熟的解决方法。但也有问题不是很清楚: 列出两个字符串的所有(我指的不是编辑操作中最短的一个) 列出两个序列的所有 列出括号的所有可能性 我不知道用蛮力法解决这些问题。我的问题是: 是

  • 问题内容: 我发现如果在开始时初始化一个空字典,然后在for循环中向字典中添加元素(大约110,000个键,每个键的值是一个列表,并且在循环中也在增加),则速度会降低循环。 我怀疑问题在于,字典在初始化时不知道键的数量,并且执行的操作也不是很聪明,因此存储冲突可能会变得很频繁并且会减慢速度。 如果我知道键的数量以及这些键的确切含义,python中有什么方法可以使字典(或哈希表)更有效地工作?我隐约

  • fn=fn−1+fn−2,其中f1=1和f2=1。因此,前12项将为f1=1,f2=1,f3=2,f4=3,f5=5,f6=8,f7=13,f8=21,f9=34,f10=55,f11=89,f12=144 第12项f12是第一个包含三位数的项。 斐波那契数列中第一个包含1000位数字的项是什么?