Space complexity: initializing a hashmap with keys and updating its values alone vs. dynamically populating key, value pairs inside a loop
假设我有一个简单的问题,返回一个字符串中所有字符出现的索引。我知道你可以直接运行一个for循环并打印出来,但是假设我必须以某种数据结构返回它!
其他假设:我们知道这是一个ASCII字符串。字符串中不存在重复字符。
我可以做两件事中的一件。
使用所有可能的128个键和
None 作为值。遍历字符串并简单地更新dictionary/hashmap以索引作为键的值。
遍历dictionary元素,并删除那些键、值值为
None 的对。1
2
3
4
5
6
7
8ascii_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)
初始化没有键或值的空哈希映射。
遍历字符串并创建键、值对。
1
2
3
4
5
6ascii_occurrence = {}
for charIndex in string:
ascii_occurrence[string[charIndex]] = charIndex
print(ascii_occurrence)
我对这两种情况下的时间复杂性都很确定,但是我对这两种方法的空间复杂性不确定。
讨论空间复杂性:
方法1,我的空间不取决于输入的大小。您可以假设当您购买计算机以运行用于此特定目的的代码时,具有128个键的hashmap已经存在。我只是更新值,而不是创建新的键,并根据输入扩展hashmap。在这种情况下,它是O(1)。
方法2,hashmap最初是空的,其中没有任何内容,您必须通过遍历字符串用键、值对填充它。所以真的…你的字典的填充量取决于输入的大小。在这种情况下,它是O(N)。
我的论点正确吗?
这两种方法的复杂性是O(n^2),这是因为在每个迭代中都有一个索引(
1 | ascii_occurrence = {charIndex: ind for ind, charIndex in enumerate(string)} |
在这种情况下,除了不通过索引获取字符之外,您不需要将项目分配给以前创建的字典。相反,python将根据需要为您创建字典,这样可以节省您在每次迭代时调用
从运行时和内存的角度来看,这段代码的复杂性当然是O(n)。
现在,如果你正在寻找一种更优化的方法,这很容易实现,但是你必须牺牲一些其他的东西。也就是说,如果您想要更少的运行时,您应该放弃一些内存,反之亦然。但如果你不想这样做,你可能会考虑在你达到这一点之前创建你的字典。您可以在创建主字符串时创建字典。这里还有其他一些棘手的方法,比如通过将枚举对象直接传递给
1 | ascii_occurrence = dict(enumerate(string)) |