C++ 在这种情况下,哪个更有效:std::vector<;布尔>;或标准::无序地图<;int>;?
我知道一个经典的编程面试问题是“给定一个N-1整数数组,这些整数是数字1到N,其中一个缺失,找到缺失的数字。”我认为C++ 在这种情况下,哪个更有效:std::vector<;布尔>;或标准::无序地图<;int>;?,c++,C++,我知道一个经典的编程面试问题是“给定一个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
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;
}
但我想知道,如果使用类似的过程处理
无序的\u map
,总体上是否会更快?我认为实例化一个无序的映射的每个成员需要更长的时间,但是修改它的元素可能需要更快的时间 您使用的上述技术是的基础,并额外保证无重复,使其更加有效。因此,该算法是O(n)(紧界) 一个
std::unordered_集
对于每个n-1插入有O(1)个预期和O(n)个最坏情况的复杂性,但对于总共O(n)个预期和O(n*n)个最坏情况。即使预期(和最佳)情况下的复杂性相同,
std::unordered_set
是一个复杂得多的容器,因此在任何情况下都会失去竞争
std::vector
不包含任何bool
,但它是一种使用代理来节省空间的专门化(被广泛认为是设计失败)因此,使用不同的
vector
实例化,使用char
甚至int
将消耗更多的可修改内存,但可能由于更高效的代码(无位旋转)而更高效
无论如何,两种实现的效率都相形见绌,只需简单地添加元素并从不间断序列的总和中减去,就像这样
向量
在这种情况下,n
是有界的,应该能够击败无序映射
。无序映射
的底层数据结构本质上是一个向量
,其中取散列,取散列的模来选择向量中开始的索引。(向量存储哈希表“bucket”)因此,普通的向量已经是一个完美的哈希表,并且您从数组中得到了一个完美的哈希--N!因此,unordered_map
提供的额外机制将是您不使用的开销
(这是假设您不会碰巧陷入这样的情况,unordered_map
由于散列冲突而具有O(n)查找复杂性)
也就是说,vector
由于vector
bool*offBooEnd=booVec.end()的位场行为,可能会击败vector
代码>,因为std::vector
专用于使用位字段存储元素。@cdhowie:my bad。需要进行编辑。即使在编辑之后也不确定您的代码是否有效。vector::iterator
是否保证随机访问?否则你不能加减它们。使用std::distance
,或者更好地使用vector
。为什么不简单地将所有数字相加?第一个n
整数的和是n(n+1)/2
,对数组中的数字求和并调用该s
。然后n(n+1)/2-s
是缺失的数字。这比在任何集合中分配n
元素都要快。并定义最佳值。即使您通过使用比vector
更喜欢的容器来降低算法复杂性,对于N
的最合理值,也很难击败vector
的运行时性能。unorderedxxx
容器是平均情况下的O(1)
和最坏情况下的O(N)
,从不O(lgn)
@Billy:更正。谢谢你。
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;
}
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;
}