【发布时间】:2011-02-02 18:16:16
【问题描述】:
给定一个 STL 向量,仅按排序顺序输出重复项,例如,
INPUT : { 4, 4, 1, 2, 3, 2, 3 }
OUTPUT: { 2, 3, 4 }
该算法是微不足道的,但目标是使其与 std::unique() 一样高效。我的幼稚实现就地修改了容器:
我的幼稚实现:
void not_unique(vector<int>* pv)
{
if (!pv)
return;
// Sort (in-place) so we can find duplicates in linear time
sort(pv->begin(), pv->end());
vector<int>::iterator it_start = pv->begin();
while (it_start != pv->end())
{
size_t nKeep = 0;
// Find the next different element
vector<int>::iterator it_stop = it_start + 1;
while (it_stop != pv->end() && *it_start == *it_stop)
{
nKeep = 1; // This gets set redundantly
++it_stop;
}
// If the element is a duplicate, keep only the first one (nKeep=1).
// Otherwise, the element is not duplicated so erase it (nKeep=0).
it_start = pv->erase(it_start + nKeep, it_stop);
}
}
如果您可以使其更高效、更优雅或更通用,请告诉我。例如,自定义排序算法,或在第二个循环中复制元素以消除erase() 调用。
【问题讨论】:
-
std::unique() 假定向量已排序。您能否详细说明您认为您的代码效率较低的原因?
-
只是为了挑选您所拥有的:通过引用获取容器。没有理由在这里使用指针(例如,使用
keep_duplicates(0)并不安全。)函数内部的代码和函数的调用都会稍微简化一些。 :) -
澄清一下:如果输入是
{1, 1, 1},输出应该是{1}还是{1, 1}? -
这不是 O(n)。由于
erase具有线性复杂度,所以它是 O(n^2),在 while 循环内部,它也具有线性复杂度。 -
@GMan:我总是通过指针传递输出参数以指示它们可以被修改。这样,当用户看到像“foo(a, b, &c, &d);”这样的函数调用时,他们无需阅读文档即可知道哪些参数是输入和输出。不利的一面是,正如您所指出的那样,实现有点复杂(是的,它应该检查 NULL)。
标签: c++ algorithm stl performance unique