是否可以在线性时间内进行一般排序?

时间:2013-02-20 02:15:56

标签: c++ algorithm

我正在尝试在O(n)时间解决一个问题,在给定两个前向迭代器到容器前面和容器后面的情况下,我想删除容器中没有出现的所有元素至少<这个数字>时间。例如,给定一个字符串向量,如(“john”,“hello”,“one”,“yes”,“hello”,“one”),我想删除所有出现少于2次的元素,最终的向量将包含just(“hello”,“one”)。

我在想,如果我能在O(n)时间内进行一般排序,我可以完成这个结果(在O(n)时间内),但是我很难用字符串,整数,字符或者可以使用的任何其他东西(一般来说)。我是否正确地思考这个问题,还是有更简单的方法来解决问题?

4 个答案:

答案 0 :(得分:2)

是的,你实际上并没有排序,而是删除元素。

1)。将每个单词存储到哈希集中。 2)。查找并仅在hashset中添加。

答案 1 :(得分:2)

简答:不。基于比较的排序需要O(n log n)次。 (这可以被正式证明。)如果您对输入有所了解(例如,输入在已知范围内随机均匀分布),那么您可以在O(n)时间内使用众所周知的算法,例如桶排序或基数排序。与@Mooing Duck相反,在O(1)时间内没有排序(这应该是显而易见的 - 对于任何排序算法,您必须至少访问每个元素一次)。

但是,正如其他几个海报所说,你的问题不需要排序算法......

答案 2 :(得分:1)

无需排序

1)填充std::unordered_map<string,vector<int>> indexOfStrings; - O(N)

2)对于string的每个vector size() < 2,删除元素 - O(删除次数)&lt; = O(N)

indexOfStrings - 存储字符串每次出现的索引。这允许从矢量快速删除而无需搜索。

答案 3 :(得分:1)

您不需要排序,只需要unordered_map

unordered_map<string, int> counter;
vector<string> newvec;
for(string &s : v) {
    if((++counter[s]) == 2) {
        newvec.push_back(s);
    }
}

请注意,这是C ++ 11代码。 (感谢@jogojapan提供的代码改进建议)。