均匀地分配列表中的所有项目

时间:2010-07-30 10:20:23

标签: algorithm math

我有一段时间遇到这个问题,仍在努力解决问题。

在列表中均匀分配项目的最佳方法是什么?差异很小?

假设我们在数组中有一个列表或元素:

Red, Red, Red, Red, Red, Blue, Blue, Blue, Green, Green, Green, Yellow

理想情况下,输出会产生类似的结果:

Red, Blue, Red, Green, Red, Yellow, Blue, Red, Green, Red, Blue, Green.

每个实例尽可能“远离”自身的另一个实例......

当我第一次尝试尝试解决这个问题时,我必须承认我天真,所以我只是使用某种形式的种子随机数来洗牌,但这会导致实例聚集。

建议是从频率最高的项目开始,所以红色将被放置在n * 12/5的位置,n从0到4(包括0和4)。

然后将下一个最重复的元素(蓝色)放在n * 12/3 + 1的位置,从0到2(包括0和2)。如果已经有东西放在那里,只需把它放在下一个空位。然而,当它在纸上记录时,这并不适用于所有情况,

说清单只是

Red, Red, Red, Red, Red, Blue

它会失败。

其中任何一个选项都有三个相同颜色的邻接

Red, Red, Blue, Red, Red, Red
Red, Red, Red, Blue, Red, Red

那么,任何想法或实现如何做到这一点都会很棒。

如果重要的是我正在研究objective-c,但现在我关心的是如何做到的方法。

6 个答案:

答案 0 :(得分:6)

一个简单的想法:为每种类型的项目使用单独的列表。然后使用类似合并排序的东西将每个列表中的一个项目插入到新列表中,始终按相同的顺序排列。跳过空列表。

这当然不会产生完美的解决方案,但它很容易实现并且应该很快。一个简单的改进是按大小排序列表,最大的是。这比列表的随机顺序提供了更好的结果。

更新:也许这可能会让它变得更好:在算法开始时获取最大列表的大小并将其称为LARGEST_SIZE - 这一轮将在每一轮中得到轮流。现在对于所有其他列表,它们应仅在starting_size_of_the_list/LARGEST_SIZE轮中使用。我希望你知道我的意思。这样您就可以均匀地分隔所有项目。但是,它仍然不完美!

好的,所以我会尝试更具体。假设您有4个尺寸列表:30 15 6 3

对于第一个列表,您将每30/30轮使用它,这是1,所以每1轮。这意味着每一次。对于第二个列表,您将使用它15/30,即每2轮0.5。第三名:6/30 - >每5回合一次。上次排行:3/30 - >每10回合一次。这应该真的给你一个很好的间距。

这当然是一个很好的例子,对于其他数字来说它有点丑陋。对于非常少量的物品,这不会得到完美的结果。然而,对于大量的物品,它应该工作得很好。

答案 1 :(得分:5)

您可以生成一系列有理数字,表示每种颜色的间距均匀。然后,对所有这些数字进行排序。

示例:

  • B:数字为(1/10 3/10 5/10 7/10 9/10)
  • R:数字是(1/6 3/6 5/6)
  • 排序:((1/10“B”)(1/6“R”)(3/10“B”)(5/10“B”)(3/6“R”)(7/10 “B”)(5/6“R”)(9/10“B”))
  • => B R B B R B R B

当数字相等时,应用二级排序,这可以是任意的,但应该是一致的。

请注意,各个序列已经排序,因此您可以通过合并进行排序,在这种情况下只需 O(n·log m) n 是所有计数的总和, m 颜色的数量)。这可以通过懒惰地生成数字来进一步优化。

最终算法不需要显式排序:

  • B计数器设置为(/(* 2 5))=> 1/10
  • R计数器设置为(/(* 2 3))=> 1/6
  • B步骤设置为B计数器
  • 的两倍
  • R步骤设置为R计数器
  • 的两倍
    • 使用最低计数器中的一种颜色并将其放入结果
    • 以步长
    • 计数的步骤
    • 直到所有计数器都是> = 1

由于你需要循环的 n 步骤,并且每次必须找到最小的 m 数字,这似乎在 O上运行(n·n米)。但是,您可以将计数器保持在最小堆中,以便将其再次降低到 O(n·log m)

答案 2 :(得分:4)

我将在这里发布解决方案,我在一些情况下使用它来解决算法竞赛中的这个问题。

您将拥有最大堆对(COUNTER,COLOR),按COUNTER排序,因此具有最大COUNTER的颜色将位于顶部。每次你有两种情况:如果顶部的值与列表中的最后一个元素不相等,你将从堆中删除该对(COUNTERx,COLOURx),将COLOURx添加到列表的末尾,如果(COUNTERx) - 1!= 0,则将对((COUNTERx) - 1,COLOURx)添加到堆中。在另一种情况下,从堆中取第二个最大的COUNTER对而不是第一个,并对第一对执行相同的操作。时间复杂度为o(S log N),其中N是颜色数,S是列表的大小。

答案 3 :(得分:3)

您可以执行K-means clustering的倒数,目标是:

  • 最大化群集数量
  • 使用某种反函数定义项目与相似项目的接近程度,以便从相似的项目创建聚类,这些项目相距更远而不是靠近在一起。

答案 4 :(得分:1)

我认为您需要针对某种改进功能进行优化 - 比如说计算在某个位置插入蓝色会有多“好”,并为所有可能的插入位置执行此操作然后插入到任何位置使用此“增益”功能的最大值并继续。

答案 5 :(得分:1)

使用动态评分函数对列表进行排序,列表中的每个元素都会返回距离具有相同值的最近元素的距离。