C++ 在这种情况下,哪个更有效:std::vector<;布尔>;或标准::无序地图<;int>;?

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

我知道一个经典的编程面试问题是“给定一个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;       
}

但我想知道,如果使用类似的过程处理
无序的\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;
}