混淆哈希映射的时间复杂度
Confusion about time complexity with hash maps
在 leetcode 上,我发现“忽略”涉及哈希映射的最坏情况时间复杂度是很常见的。我认为在软件采访中,像他们经常做的那样假设“最坏情况”是标准的。下面是我对一个简单问题的解决方案。问题是找到字符串中的第一个非重复字符。我知道散列图平均为 O(1) 查找。但是当遍历字符串并查找散列图时,为什么时间复杂度不是 O(N^2) 而是 O(N)?
#include <unordered_map>
class Solution {
public:
unordered_map<char, int> m;
int firstUniqChar(string s) {
for(char c : s) {
m[c]++;
}
for(int i =0; i < s.length(); i++) {
if(m[s[i]] == 1) {
return i;
}
}
return -1;
}
};
它平均 O(N)
因为哈希映射平均每次查找 O(1)
而你做了 O(N)
个。
平均 表示对所有可能的输入进行平均。这意味着可能存在一个输入数组,该数组破坏了特定的哈希值并在每次查找时达到 O(N)
或更糟。
最坏的情况在很大程度上是特定于实现的——例如散列到桶中取决于元素如何存储在每个桶中。如果它们在一个简单列表中,则查找是 O(<duplicates>)
,二叉树会将其降低到 O(log<duplicates>)
。搜索存在和丢失的密钥之间也可能存在差异。
还有一个很大的假设,即所有散列容器都可以随着存储的元素数量而增长。 IE。保持桶的占用率低。
在采访中提及他们最坏的情况并没有坏处,这表明您知道他们是有极限的。
给定问题的时间复杂度为 O(N)。你可以为它提供一个 perfect hash function,那是不会发生碰撞的。这里这个完美的哈希函数是static_cast<size_t>(256+c)
。好吧,如果你在 leetcode 上查看这个问题的最快解决方案,你会发现人们使用普通数组。
在 leetcode 上,我发现“忽略”涉及哈希映射的最坏情况时间复杂度是很常见的。我认为在软件采访中,像他们经常做的那样假设“最坏情况”是标准的。下面是我对一个简单问题的解决方案。问题是找到字符串中的第一个非重复字符。我知道散列图平均为 O(1) 查找。但是当遍历字符串并查找散列图时,为什么时间复杂度不是 O(N^2) 而是 O(N)?
#include <unordered_map>
class Solution {
public:
unordered_map<char, int> m;
int firstUniqChar(string s) {
for(char c : s) {
m[c]++;
}
for(int i =0; i < s.length(); i++) {
if(m[s[i]] == 1) {
return i;
}
}
return -1;
}
};
它平均 O(N)
因为哈希映射平均每次查找 O(1)
而你做了 O(N)
个。
平均 表示对所有可能的输入进行平均。这意味着可能存在一个输入数组,该数组破坏了特定的哈希值并在每次查找时达到 O(N)
或更糟。
最坏的情况在很大程度上是特定于实现的——例如散列到桶中取决于元素如何存储在每个桶中。如果它们在一个简单列表中,则查找是 O(<duplicates>)
,二叉树会将其降低到 O(log<duplicates>)
。搜索存在和丢失的密钥之间也可能存在差异。
还有一个很大的假设,即所有散列容器都可以随着存储的元素数量而增长。 IE。保持桶的占用率低。
在采访中提及他们最坏的情况并没有坏处,这表明您知道他们是有极限的。
给定问题的时间复杂度为 O(N)。你可以为它提供一个 perfect hash function,那是不会发生碰撞的。这里这个完美的哈希函数是static_cast<size_t>(256+c)
。好吧,如果你在 leetcode 上查看这个问题的最快解决方案,你会发现人们使用普通数组。