空间复杂度:使用键初始化哈希图并单独更新其值与在循环内动态填充键、值对
Posted
技术标签:
【中文标题】空间复杂度:使用键初始化哈希图并单独更新其值与在循环内动态填充键、值对【英文标题】:Space complexity: initializing a hashmap with keys and updating its values alone vs. dynamically populating key, value pairs inside a loop 【发布时间】:2019-01-12 14:01:31 【问题描述】:假设我有一个简单的问题,涉及返回字符串中所有字符的出现索引。我知道你可以直接运行一个 for 循环并将其打印出来,但假设我必须以某种数据结构返回它!
其他假设:我们知道这是一个 ASCII 字符串。字符串中不存在重复字符。
我可以做两件事之一。
预先使用所有可能的 128 个键初始化 hashmap 和
None
作为值。
遍历字符串并简单地更新字典/哈希图 以索引作为键的值。
遍历字典元素,并删除那些键、值
值为None
的对。
ascii_occurrence = 'a': None, 'b': None, 'c': None ... char#128: None #Initialize a hashmap with each of the 128 characters as key, and set None to its value.
for charIndex in string:
ascii_occurrence[string[charIndex]] = charIndex
indexMap = k: v for k, v in ascii_occurrence.items() if v is not None
print(indexMap)
初始化一个没有键或值的 EMPTY 哈希图。
遍历字符串并创建键值对。
ascii_occurrence =
for charIndex in string:
ascii_occurrence[string[charIndex]] = charIndex
print(ascii_occurrence)
我确定这两种情况的时间复杂度都是 O(N),但我不确定这两种方法的空间复杂度。
关于空间复杂性的争论:
方法 1,我的空间不“依赖”输入的大小。您可以假设当您购买计算机以运行用于此特定目的的代码时,已经存在具有 128 个键的哈希图。我只是更新值,而不是创建新键并根据我的输入扩展哈希图。在这种情况下,它是 O(1)。
方法 2,hashmap 最初是空的,其中没有任何内容,您必须通过遍历字符串来使用键、值对填充它。所以真的.. 你要填充多少字典取决于输入大小。在这种情况下,它是 O(N)。
我的论点正确吗?
【问题讨论】:
【参考方案1】:这两种方法的复杂性都是 O(N^2),这是因为每次迭代都有一个索引 (string[charIndex]
)。但是,在这种情况下,您的第二种方法通常是更好的方法。但是您也可以使用以下字典理解以更优化的方式(就运行时而言)来完成它:
ascii_occurrence = charIndex: ind for ind, charIndex in enumerate(string)
在这种情况下,除了没有获取带有索引的字符之外,您不需要将项目分配给以前创建的字典。相反,Python 会根据需要为您创建字典,这样您就可以在每次迭代时调用 __setitem__
函数,这本身就是暂停和恢复函数帧的组合。
这个sn-p在运行时间和内存方面的复杂度当然是O(N)。
现在,如果您正在寻找一种更优化的方法,这很容易实现,但您必须牺牲一些其他的东西。这就是说,如果你想要更少的运行时间,你应该放弃一些内存,反之亦然。但是,如果您不想这样做,您可能需要考虑在达到这一点之前创建您的字典。您可以在创建主字符串时创建字典。您还可以在此处执行其他一些棘手的方法,例如通过将枚举对象直接传递给dict
对象来创建dict
。但在这种情况下,索引将成为键,字符将成为值。
ascii_occurrence = dict(enumerate(string))
【讨论】:
感谢您的回答!你能更详细地向我解释一下为什么它是 O(N^2) 吗?据我所知,您正在遍历字符串一次,并且在循环内,您正在设置键的值,不是或在字典中获取项目 O(1)?以上是关于空间复杂度:使用键初始化哈希图并单独更新其值与在循环内动态填充键、值对的主要内容,如果未能解决你的问题,请参考以下文章