为什么矢量比unordered_map快?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么矢量比unordered_map快?相关的知识,希望对你有一定的参考价值。
我在LeetCode上解决了一个问题,但是还没有人能够解释我的问题。
问题是这样的:
给定一个任意赎金票据字符串和另一个包含所有杂志字母的字符串,写一个函数,如果赎金票据可以从杂志上构建,它将返回true;否则,它将返回false。
杂志字符串中的每个字母只能在赎金票据中使用一次。
注意:您可以假设两个字符串仅包含小写字母。
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
My code (which takes 32ms):
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if(ransomNote.size() > magazine.size()) return false;
unordered_map<char, int> m;
for(int i = 0; i < magazine.size(); i++)
m[magazine[i]]++;
for(int i = 0; i < ransomNote.size(); i++)
{
if(m[ransomNote[i]] <= 0) return false;
m[ransomNote[i]]--;
}
return true;
}
};
The code (which I dont know why is faster - takes 19ms):
bool canConstruct(string ransomNote, string magazine) {
int lettersLeft = ransomNote.size(); // Remaining # of letters to be found in magazine
int arr[26] = {0};
for (int j = 0; j < ransomNote.size(); j++) {
arr[ransomNote[j] - 'a']++; // letter - 'a' gives a value of 0 - 25 for each lower case letter a-z
}
int i = 0;
while (i < magazine.size() && lettersLeft > 0) {
if (arr[magazine[i] - 'a'] > 0) {
arr[magazine[i] - 'a']--;
lettersLeft--;
}
i++;
}
if (lettersLeft == 0) {
return true;
} else {
return false;
}
}
这两者具有相同的复杂性并使用相同的结构来解决问题,但我不明白为什么一个人花费的时间几乎是另一个的两倍。查询向量的时间是O(1),但对于unordered_map它是相同的。向其中任何一个添加条目/密钥的情况相同。
请问,有人可以解释为什么运行时间变化如此之大?
首先要注意的是,虽然查询unordered_map
的平均时间是不变的,但最糟糕的情况不是O(1)
。你可以看到here它实际上升到O(N)
的顺序,N
表示容器的大小。
其次,由于vector
分配了内存的连续部分,因此即使在最坏的情况下,访问该内存也非常高效且实际上是恒定的。 (即简单的指针算法,而不是计算更复杂的散列函数的结果)还有可能涉及可能涉及的顺序存储器的各种级别的缓存(即,取决于您的代码运行的平台),这可能是与使用vector
的代码相比,使用unordered_map
执行代码的速度更快。
实质上,就复杂性而言,vector
的最坏情况性能比unordered_map
更有效。最重要的是,大多数硬件系统都提供缓存等功能,这使得vector
的使用范围更大。 (即O(1)
操作中较小的常数因素)
您的第二种方法使用普通C数组,其中访问元素是一个简单的指针取消引用。但unordered_map
的情况并非如此。有两点需要注意:
- 首先,访问元素不是简单的指针取消引用。它必须做其他工作来维护它的内部结构。
unordered_map
实际上是一个哈希表,C ++标准间接要求it to be implemented using open addressing,这是一个比简单数组访问更复杂的算法。 - 其次,O(1)访问平均而不是最坏情况。
由于这些原因,即使它们具有相同的运行时复杂性,也难怪阵列版本比unordered_map
工作得更好。这是另一个具有相同运行时复杂度的代码执行不同的示例。
只有当你有大量的钥匙时才会看到unordered_map
的好处(这里与固定的26相对)。
以上是关于为什么矢量比unordered_map快?的主要内容,如果未能解决你的问题,请参考以下文章
Idea插件PlantUml,比Visio快10倍的画图工具(少量夸张!)