【问题标题】:Deleting elements in a vector删除向量中的元素
【发布时间】:2015-03-29 10:39:13
【问题描述】:

我有一个结构向量

结构有两个元素X和Y,其值如下图所示。

假设:

索引 0 1 2 3 4 5 6 7 8 9

值 a,b c,d e,f g,h a,b a,i a,i a,i j,k l,m

我的问题:** 我需要保留元素 (x,y) 的**最新出现,并在有效的时间内删除其余元素,并可能使用辅助空间。

说,我从向量的开头开始,遇到元素(a,b),我需要删除这个元素加上所有其他的(a,x)s,这里x可以是任何东西,但不能b,但保留最新的 (a,b)。

在这里,我需要删除索引 0、5、6、7 处的元素,并保留 4 处的元素。

元素是使用 vector.push_back() 插入的,因此最新的元素是最后插入的元素。 (插入模仿队列)

我的进步:

i) 我尝试了一个稳定的排序,但考虑到我可能会遇到 O(nlogn) 复杂性,我对这种方法不感兴趣。

ii) 这样的设计,我只能从头开始迭代,而我不能逆转它并从头开始。

iii) 为了降低复杂性,我做了类似的事情:

 - Iterate vector from start to end.

 - For every elements, keep the search area to a smaller one by searching from the end.

 - Then delete all elements between current positions of forward iterator and the reverse iterator. This does not take the above illustrated case into consideration and works only when the most recent element is towards the end, i.e.in the above case, all (a,i)s are before the last (a,b)

【问题讨论】:

  • 您的问题是关于效率还是只是如何从向量中删除?
  • 我在您的...问题中找不到任何问题...
  • 我认为您应该将向量复制到新向量,只保留您想要保留的元素。这是在一个 for 循环中完成的,我认为您不太可能做得比这更有效。
  • @AlexPetrenko:我尝试在一次迭代中使用位集和标记元素,然后在后续迭代中使用设置位删除元素。但是,我正在寻找一种有效的方法(如果存在)。

标签: c++ algorithm vector


【解决方案1】:

我想不出比天真的方法更快的方法:

#include <vector>
#include <algorithm>

using namespace std;

struct S {
    char X;
    char Y;
};

bool operator==(const S& lhs, const S& rhs ) {
    return lhs.X == rhs.X && lhs.Y == rhs.Y;
}

int main(){
    std::vector < S > src = { { 'a', 'b' }, { 'c', 'd' }, { 'e', 'f' }, { 'g', 'h' }, { 'a', 'b' }, { 'a', 'i' }, { 'a', 'i' }, { 'a', 'i' }, { 'j', 'k' }, { 'l', 'm' } };

    auto srcIt = begin(src);
    while (srcIt != end(src)) {
        // find last identical element
        auto le = find(rbegin(src), rend(src), *srcIt).base() - 1;

        char x = srcIt->X; 
        // delete all elements with same X value after last element 
        src.erase(std::remove_if(le + 1, end(src), [=](const S& e){return x == e.X; }), end(src));
        // delete all elements with same X value up to last element
        src.erase(std::remove_if(srcIt, le, [=](const S& e){return x == e.X; }), le);

        srcIt++;
    }

    for (auto& e : src) {
        std::cout << e.X << "," << e.Y << " - ";
    }
    std::cout << std::endl;
}

我不确定是否可以将其转换为单遍算法,但即便如此,您必须测试的值的数量会在每一步中增加,因此这会导致类似的结果渐近复杂度(可能少一些副本),但代码可能更复杂。

原则上,您可以在两个缓冲区之间用copy_if 替换erase remove,但我看不出这将如何提高性能,除非您想在问题上抛出多个线程。在这种情况下,我会让每个线程将选定的元素复制到一个单独的缓冲区中,然后在每次迭代结束时将它们连接起来。

【讨论】:

  • 感谢迈克的努力。
  • @thenoGk:不用担心。如果您找到更好的解决方案,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多