甚至是整数组

时间:2012-01-05 22:23:50

标签: javascript algorithm

给定一个整数数组heights我想将它们分成n个集合,每个集合具有相等的totalHeight(集合中的值的总和),或尽可能接近。在集合中的每个值之间必须有固定的距离gap。集合不必具有相同数量的值。

例如,假设:

  • heights[0, 1, 2, 3, 4, 5] = [120, 78, 110, 95, 125, 95]

  • n = 3

  • gaps = 10

可能的安排是:

  • a[0, 1], b[2, 3], c[4, 5]提供totalHeight

    • a = heights[0] + gap + heights[1] = 120 + 10 + 78 = 208

    • b = heights[2] + gap + heights[3] = 110 + 10 + 95 = 215

    • c = heights[4] + gap + heights[5] = 125 + 10 + 95 = 230

  • a[0], b[1, 2, 3], c[4, 5]提供totalHeight

    • a = heights[0] = 120

    • b = heights[1] + gap + heights[2] + gap + heights[3] = 303

    • c = heights[4] + gap + heights[5] = 125 + 10 + 95 = 230

等等。我想找到能够提供最均匀尺寸的组合的组合。因此,在此示例中,第一个组合更好,因为它给出了总体错误:

max - min = 230 - 208 = 22

而第二个组合给出的错误是183.我试图在JavaScript中这样做,但我只是在寻找某种算法的轮廓。伪代码或其他任何东西都会很棒。任何帮助都将受到高度赞赏。

我的不良尝试:显然,解决这个问题的一种方法就是尝试所有可能的组合。一旦heights变大,这将是可怕的。

我尝试的另一种方法是获得集合的预期平均高度,计算为height / n中值的总和。然后我尝试通过尽可能接近这个平均值来单独填充每个集合。在某些情况下它可以正常工作,但它太慢了。

注意:如果有帮助,我很乐意拥有对称集。例如,对于集合(a,b c),a = b。或者有五组(a,b,c,d,e),a = b和c = d。我认为这将更难实施,但我可能是错的。

编辑:对于任何可能感兴趣的人,我能想出的最好的是以下算法:

  • 按降序排序heights
  • 创建n套。
  • n中的第一个heights值放入每个集的第一个插槽中。即将n最大值放在每组的开头。添加heights时删除值。
  • heights.count> 0
    • 在每个totalHeight集中找到最小的gap(包括n)。
    • heights中的下一个值添加到此集合中(并从heights中删除该值)。
  • 然后在最后有一些小算法,如果x接近平均值,每个集合可以与其他集合进行totalHeight次交换。我保持x小,因为这个过程可以永远持续下去。

这并不可怕,但显然并不完美。

2 个答案:

答案 0 :(得分:2)

似乎它是NP完全的并且可以简化为Subset sum problem或更精确地归结为Partition problem

答案 1 :(得分:0)

你的第二种方法 - 找到平均值(高度/ n),然后尝试用尽可能接近的均值填充集合似乎是一种很好的实用方法。你说这太慢了......下面的实现是O(n * m log n),其中m是集合中允许的最大元素数。如果m可能非常大,那么这可能会非常慢,但是如果m被限制在一定范围内,那么它可以接近O(n log n),这大约是你要得到的速度。

   Find the mean height of all values. h_mean = Sum(h) / n; O(n).
   Sort all heights. O(n log n).
   Examine the highest and lowest height. 
   Add the value which is furthest from the mean to a new set.
   Remove this value from the sorted heights.
   Repeat for max_number allowed in set = 1 .. m (m < n / 2)
   {
      Repeat:
      {
         If the set mean is higher than the mean.
            Add the lowest value from the sorted heights.
            Remove this value from the sorted heights.
         If the set mean is lower than the mean
            Add the highest value from the sorted heights.
            Remove this value from the sorted heights.
         Recalculate the set mean (taking account of the gap).
         If the new set mean is further from the h_mean than the last OR
            If the set has too many elements
           break
      }
      Until all numbers are used.
      Keep track of the standard deviations for this assignment. 
      If this assignment is the best so far, keep it.
   }

这不会给出一个可证明的最佳解决方案,但它很简单,并且有很多工作要做......

注意,在此算法中,所有集合都具有相同数量的元素m。你重复m的不同值的迭代,比如2,3,4(注意m应该是N的因子)。每组最终总高度大约为m * mean_height。

你可能会问,如果N是素数,那该怎么办?

然后很明显,一组将重视总价值。

这是否意味着此算法无用?

完全没有。这很简单,应该首先尝试解决方案。您可能希望首先使用此算法,然后使用优化技术(例如选择性交换高度为集合)来优化第一个结果。