【问题标题】:Efficiency of dictionaries in python:python中字典的效率:
【发布时间】:2018-04-21 16:06:48
【问题描述】:

在下面的递归函数中,我在 python 中应用了一些记忆技术来将以前的计算值保存在字典中,理论上应该有 O(1) 的存储和检索。但是,使用 memoization 的执行时间大约是简单递归的三倍。

在下面的两段代码中,第二段代码执行时间如此长的可能原因是什么?我是不是用错了字典?

简单的递归函数:

import time

def deletion_distance(str1, str2):
  if str1 is "":
    return len(str2)
  elif str2 is "":
    return len(str1)
  else:
    if str1[len(str1) - 1] == str2[len(str2) - 1]:
      return deletion_distance(str1[:-1],str2[:-1])
    else:
      return 1 + min(deletion_distance(str1, str2[:-1]),deletion_distance(str1[:-1],str2))

str1 = "dragonified"
str2 = "infinitezimal"

start = time.time()
for i in range(0,2):
    deletion_distance(str1,str2)
end = time.time()

print((end - start) / 2)

使用字典进行动态编程:

import time

def deletion_distance(str1, str2):
  global aux_dict

  if str1 is "":
    return len(str2)
  elif str2 is "":
    return len(str1)
  else:
    if str1[len(str1) - 1] == str2[len(str2) - 1]:
      if "1"+str1[:-1]+"2"+str2[:-1] in aux_dict:
        return aux_dict["1"+str1[:-1]+"2"+str2[:-1]]
      else:
        aux_dict["1"+str1[:-1]+"2"+str2[:-1]] = deletion_distance(str1[:-1],str2[:-1])
        return aux_dict["1"+str1[:-1]+"2"+str2[:-1]]
    else:

      return 1 + min(
        aux_dict["1"+str1+"2"+str2[:-1]] if "1"+str1+"2"+str2[:-1] in aux_dict else deletion_distance(str1, str2[:-1]),
        aux_dict["1"+str1[:-1]+"2"+str2] if "1"+str1[:-1]+"2"+str2 in aux_dict else deletion_distance(str1[:-1],str2))

aux_dict = {}      
str1 = "dragonified"
str2 = "infinitezimal"

start = time.time()
for i in range(0,2):
    deletion_distance(str1,str2)
end = time.time()

print((end - start) / 2)

这两个函数都计算两个字符串的删除距离(PRAMP.COM 问题),这只是两个字符串的最小字符数,可以从两个字符串中删除,使它们变得相同。

【问题讨论】:

  • 注意:如果未命中数远大于命中数,即您主要存储在字典中而不是读取,那么记忆可能会恶化而不是提高性能。
  • 不要使用is比较字符串。
  • 是的,你做错了。 aux_dict 不能是本地人。
  • 这是否被正确记忆?您的函数调用每次都会创建一个新的空dict...我错过了什么吗?
  • @Nelsão 因为this

标签: python dictionary recursion dynamic-programming memoization


【解决方案1】:

您根本不使用字典,因为您为每个函数调用使用了一个新的空字典。

aux_dict = {}

def deletion_distance(str1, str2):
    if (str1, str2) in aux_dict:
        return aux_dict[str1, str2]
    if not str1:
        return len(str2)
    elif not str2:
        return len(str1)
    elif str1[-1] == str2[-1]:
        result = deletion_distance(str1[:-1],str2[:-1])
    else:
        result = 1 + min(
            deletion_distance(str1, str2[:-1]),
            deletion_distance(str1[:-1], str2),
        )
    aux_dict[str1, str2] = result
    return result

这将两个示例字符串的调用次数从 1685178 减少到 268,因此缓存版本的速度提高了 3000 倍。

编辑:在您更新的问题中,您仍然没有正确使用字典。只有在两个字符串的最后一个字符相等的情况下,才使用字典。

【讨论】:

  • 是的。我确实在我的代码上修复了它,但第二个版本仍然较慢。在问题中修复它。
  • 进行更改后,它有所改进,但仍比常规递归慢约 2 倍(每个版本使用 100000 的循环)。
猜你喜欢
  • 1970-01-01
  • 2015-03-24
  • 2018-07-20
  • 2012-04-28
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
相关资源
最近更新 更多