![](/img/trans.png)
[英]Iterator over std::unordered_map<int, std::vector<Element>>
[英]Which is more efficient in this scenario: std::vector<bool> or std::unordered_map<int>?
我知道一个经典的编程面试问题是“ 给定N-1个整数数组,它们是从1到N的数字,其中一个丢失了,找到丢失的数字 。” 我在想
int missing_number ( int * arr, int n )
{
std::vector<bool> booVec(n, false);
int * offArrEnd = arr + n;
while (arr != offArrEnd) booVec[*arr++] = true;
return std::find_first_of(booVec.begin(), booVec.end(), false)
- booVec.begin() + 1;
}
将vector<bool>
元素实例化为false
会花费很短的时间,因此可以通过booVec[*arr++]
修改其元素,这将是一个很好的解决方案。 我知道我可以通过将其更改为1来保存操作
int missing_number ( int * arr, int n )
{
std::vector<bool> booVec(n, false);
int * offArrEnd = arr + n;
while (arr != offArrEnd) booVec[*arr++] = true;
std::vector<bool>::iterator offBooEnd = booVec.end();
return std::find_first_of(booVec.begin(), offBooEnd, false)
- offBooEnd + 1;
}
但是我想知道是否对unordered_map
使用类似的过程是否整体上会更快? 我认为实例化unordered_map
每个成员将花费更长的时间,但是修改其元素可能会更快。
您上面使用的技术是Pigeonhole-Sort的基础,另外还保证了没有重复项,从而使效率更高。
因此,该算法为O(n)(紧密边界)。
但是,对于每个N-1插入, std::unordered_set
期望复杂度为O(1),最坏情况复杂度为O(n),对于期望的O(n)和最坏情况总计O(n * n)。
即使预期(和最佳)情况下的复杂性相等, std::unordered_set
还是一个更为复杂的容器,因此无论如何都失去了竞争。
std::vector<bool>
不包含任何bool
,而是一种使用代理来节省空间的专业化方法(被视为设计失败)!
因此,使用带有char
甚至int
的vector
的不同实例化将消耗更多可修改的内存,但是由于更有效的代码(无位纠错)而可能会更有效。
无论如何,通过简单地添加元素并从不中断序列的总和中减去总和,这两种实现方式的效率都 相形见 like ,例如Nikola Dimitroff的注释 。
int missing_number ( int * arr, int n )
{
unsigned long long r = (unsigned long long)n * (n+1) / 2;
for(n--)
r -= arr[n];
return (int)r;
}
在这种情况下, n
为界的vector
应该能够击败unordered_map
。 unordered_map
的基础数据结构本质上是一个vector
,在该vector
中使用哈希,并使用哈希的模数来选择从vector
开始的索引。 ( vector
存储哈希表“ buckets”)结果是,简单vector
已经是一个完美的哈希表,并且您拥有一个完美的哈希-数组中的N! 因此, unordered_map
提供的额外机制将成为您不使用的开销。
(这是假设您不会碰到由于哈希冲突而导致unordered_map
查找复杂度为O(n)的情况)
就是说,由于vector<bool>
的位域行为, vector<char>
可能会击败vector<bool>
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.