在这种情况下哪个更有效:std :: vector <bool>或std :: unordered_map <int>?</int> </bool>

时间:2014-10-31 22:30:53

标签: c++

我知道一个经典的编程面试问题是&#34; 给定一个N-1整数数组,它们是数字1到N,其中一个缺失,找到缺少的数字。&#34 ;我在想那个

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的每个成员需要更长的时间,但修改其元素可能需要更快。

2 个答案:

答案 0 :(得分:1)

您在上面使用的技术是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,但是使用代理节省空间的专业化(广泛认为是设计失败)!
因此,使用vectorchar或甚至int的不同实例化将消耗更多可修改的内存,但可能由于更有效的代码(无比特错误)而更有​​效。 / p>

无论如何,两个实现的效率相形见绌,只需添加元素并从不间断序列中减去总和,,如Nikola Dimitroff comments

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;
}

答案 1 :(得分:1)

vector有界的情况下,

n应该能够击败unordered_mapunordered_map的基础数据结构本质上是vector,其中采用散列,并且采用散列模数来选择从vector开始的索引。 (vector存储哈希表“buckets”)结果,普通vector已经是一个完美的哈希表,你有一个完美的哈希 - 数组中的N!因此,unordered_map提供的额外机制将是您未使用的开销。

(并且假设您不会遇到unordered_map因哈希冲突而导致O(n)查找复杂性的情况)

也就是说,由于vector<char>的位域行为,vector<bool>可能会超过vector<bool>