【发布时间】:2016-07-12 10:03:44
【问题描述】:
给定一个元素列表,按某个键对元素进行分组的最有效方法是什么?
例如,如果输入是{a,c,a,b,c,b,b},则有效输出可能是{a,a,b,b,b,c,c} 或{b,b,b,c,c,a,a}。
显然,如果键的类型遵循顺序,则可以使用排序算法,这将使我们得到O(nlogn) 的复杂度。
但是,密钥可能仅在相等性方面可比较,而在顺序方面则不可比较。例如,typeof(dog) != typeof(cat),但询问 typeof(dog) < typeof(cat) 是没有意义的。
当然,可以强制排序(例如obj.GetType().ToString() 并使用词法顺序),但由于不需要严格的顺序(仅分组),我想知道是否有比排序更有效的方法。
【问题讨论】:
-
你有多少钥匙? O(n) 或更小?
-
您想要“就地”分组,还是复制元素并制作另一个排序列表就可以了?
-
@OhadEytan 键的数量不同,但通常接近 1 或接近 n。我更喜欢“就地”算法,因为此操作将在许多输入上完成。
-
如果键可以分解成有序的片段序列,每个片段只能取少量值(例如,字符 1、字符 2 等),那么您可以 radix对它们进行排序(请注意,基数排序不实际上涉及任何
<或>比较)。像 Fabel 的散列解决方案可以看作是一种基数排序的第一步。 -
OTOH 如果必须将密钥视为黑匣子,我相信您能做的最好的事情就是建立一个等价类列表,如下所示:从一个空的类 L 列表开始。对于每个项目 x,将 x 与 L 中每个类的一些(任何)项目进行比较。如果这些相等测试中的任何一个成功,则将 x 添加到该类;如果它们都失败了,则向 L 添加一个仅包含元素 x 的新类。处理完所有项目后,L 包含每个组的一个类。这显然具有最坏情况的时间复杂度 O(n^2),当所有项目都不同时会发生这种情况。
标签: algorithm performance sorting time-complexity