从对矢量中获取唯一元素的有效方法

时间:2017-01-26 23:00:12

标签: c++ vector std

我有一对整数对的向量,看起来有点像:

(0, 1)
(1, 9)
(2, 3)
(6, 1)
(4, 0)

我想从中提取唯一元素,结果如下:
‍‍0‍, 1, 9, 2, 3, 6, 4 (基本上只是所有数字都没有重复)

目前我这样做:

std::vector<int> getElements(std::vector<std::pair<int, int>> S) {
    std::vector<int> V;
    for (std::vector<std::pair<int, int>>::iterator i = S.begin(); i != S.end(); i++) {
        if (std::find(V.begin(), V.end(), i->first) == V.end()) {
            V.push_back(i->first);
        }
        if (std::find(V.begin(), V.end(), i->second) == V.end()) {
            V.push_back(i->second);
        }
    }
    return V;
}

有没有更有效的方法呢?

3 个答案:

答案 0 :(得分:6)

您当前的解决方案是O(n^2)。您可以使用O(1)将已经看到过的元素的线性扫描缩减为已摊销的std::unordered_set来存储已经看过的数字;这会将您的运行时间提高到O(n)

这是一个改进的算法:

std::vector<int> getElements(std::vector<std::pair<int, int>> S) {
    std::unordered_set<int> ss;
    std::for_each(S.begin(), S.end(), [&ss](const auto& p) {
        ss.insert(p.first);
        ss.insert(p.second);
    });
    return std::vector<int>(ss.begin(), ss.end());
}

查看示例Live On Coliru

答案 1 :(得分:3)

  

有没有更有效的方法呢?

是的,有。 std::find对于向量具有O(n)复杂度,因此对每个元素重复它会给出O(n * n)复杂度。

一个简单的替代方法是将每个元素添加到std::set中。构建集合的复杂性是O(n log n)。

答案 2 :(得分:3)

未测量,但我认为它更快......

#include <iostream>
#include <algorithm>
#include <vector>

std::vector<int> getElements(std::vector<std::pair<int, int>>& S) {
    std::vector<int> V;
    V.reserve(2*S.size());
    for (const auto& i : S) {
        V.push_back(i.first);
        V.push_back(i.second);
    }
    std::sort(V.begin(), V.end());
    V.erase(std::unique(V.begin(), V.end()), V.end()); 
    return V;
}

int main() 
{
    std::vector<std::pair<int, int>> v{{0, 1},{1, 9},{2, 3},{6, 1},{4, 0}};

    for(const auto& i : getElements(v))
        std::cout << i << ' ';
    std::cout << '\n';
}