对于主要包含少量重复元素的数组进行排序的有效方法是什么?也就是说,列表如:
{10,10,55,10,999,8851243,10,55,55,55,10,999,8851243,10}
假设equal
元素的顺序无关紧要,那么什么是最坏情况/平均情况算法?
答案 0 :(得分:16)
实际上,您可以首先遍历数组并使用哈希表计算单个元素的出现次数(这是O(n),其中n =列表的大小)。然后获取所有唯一元素并对它们进行排序(这是O(k log k),其中k =唯一元素的数量),然后将其展开回O(n)步骤中的n个元素的列表,从中恢复计数哈希表。如果k <&lt;你节省了时间。
答案 1 :(得分:4)
我会尝试使用一些映射函数Counting sort。 IE浏览器。你不会使用大小等于元素范围的频率数组,而是迭代数组,写下不同的元素,并在映射函数中使用它们到频率数组。
这种算法只有一个额外的迭代和一个映射函数,它应该在一个恒定的时间内工作(使用某种哈希表)。这种方法的复杂性为O(n)
,这应该是最优的。
答案 2 :(得分:2)
不是最好的算法,但很简单:
你可以把所有东西放在一个特里,并让树叶成为柜台。这应该是O(n * m),其中n是元素的数量,m是最大元素的大小(通常是常数,但不一定是)。然后预订遍历平局,当你点击叶子时输出当前键的counter
个元素。这应该只需要O(n + p),其中p是trie的大小,与n相比应该很小。
答案 3 :(得分:1)
基于algo的C ++实现,如@Antti Huima所建议
#include <unordered_map>
#include <map>
// Modifies input array to a sorted array
// Complexity: O(n+(k*log(k))) where 'k' = number of unique elements input array
template <typename Datatype>
void SortArrayWithDuplicates(std::vector<Datatype>& in_seq) {
std::unordered_map<Datatype, int> key_counts_map;
// Count freqs O(n)
for (const auto& itr: in_seq)
key_counts_map[itr] += 1;
// Sort elements by inserting into a map O(k*log(k))
std::map<Datatype, int> key_counts_sorted_map;
for (auto const& itr: key_counts_map)
key_counts_sorted_map.insert(std::make_pair(itr.first, itr.second));
auto AlwaysTrue = [](Datatype i)->bool{return true;};
auto seq_itr = std::begin(in_seq);
// Update input sequence with new sorted values
for (auto const& itr: key_counts_sorted_map) {
std::replace_if(seq_itr, seq_itr+itr.second, AlwaysTrue, itr.first);
seq_itr += itr.second;
}
}
答案 4 :(得分:0)
IMO Pidgeonhole sort是此类数据的一个很好的例子。
我将稍微澄清一下:如果你知道数组中唯一元素的数量是合理的,并且你知道有很多重复项,我会想到实现像计数排序这样的东西,但是要创建“桶”动态列表。在第一遍之后你将摆脱重复,然后排序数组没有重复与一些良好的排序算法,然后以类似排序的方式恢复排序的数组。