可以加起来为100的百分比数组

时间:2013-04-27 20:40:07

标签: arrays algorithm data-structures

我在接受采访时被问到以下问题,我仍然在想一种有效的方法。

你有一个数组,其数字代表桶中液体的百分比。你还有一个带有方法的API:combine(int x,int y),它在数组中占两个输入百分比,并将液体从一个桶组合到另一个桶中。通过使用此信息,您必须找到100%液体可能存在的最大桶数。

示例1。数组:10,15,20,35,55,65

Ans :每桶数量为2。 自combine(65,35) ---一个100%桶, combine(55,20) - 75%桶,下一个combine(75,15) - 90%下一个combine(90,10) - 100% - 1桶 总共2桶

示例2:99,99,99

答案:自combine(99,99)以来,每桶数量为1 - 你得到一个100%的桶,其余的液体被浪费了,你不能合并任何其他桶与第三个99%的桶,使其成为100

注意:一旦您将液体从一个桶倒入另一个桶中,您就无法再次使用它 例如:combine(55,15) - 70%桶。您可以使用70%的桶,但不能使用55%和15%的桶。

2 个答案:

答案 0 :(得分:2)

您可能确实会查看bin打包问题的算法。 This student paper表示其中四个。具有最佳近似值的是降低First Fit算法。

归结为快速排序(就地,平均O(nlogn)时间复杂度和最坏情况下的O(n2)),然后是First Fit。

First Fit下来按顺序扫描垃圾箱,并将新物品放在第一个容器中,该容器足够容纳它。如果没有当前对象适合的bin,则启动一个新bin。

对于O(nlogn)复杂度的FF,使用Max Winner Tree数据结构。它有n个外部节点(播放器)和n-1个内部节点(每个匹配的赢家), 获胜者是具有最大价值的玩家。

答案 1 :(得分:1)

假设给定数组中的所有百分比都小于100(在任何情况下,如果元素大于或等于100,我们可以立即计算并删除它们),每个100%的桶不能从少于两个数组创建元素和100%桶的数量不能超过数组之和除以100.因此,检查的可能性受以下因素约束:

maxNumBarrels array = min (div (sum array) 100) (div (length array) 2)

以下Haskell代码提供了函数divide,它将数组划分为n个分区的所有变体而不重复(即,忽略分区中的分区顺序和元素顺序)。函数maxBarrels向后搜索,首先将数组划分为maxNumBarrels分区(搜索结果为maxNumBarrels元素的总和> = 100),然后逐渐减少分区数,直到找到答案或为null set返回。

import Data.Map (adjust, fromList, toList)

divide xs n = divide' xs (zip [0..] (replicate n [])) where
  divide' []     result = [result]
  divide' (x:xs) result = do
    index <- indexes
    divide' xs (toList $ adjust (x :) index (fromList result)) where
      populated = map fst . filter (not . null . snd) $ result
      indexes = populated ++ if any (null . snd) result 
                                then [length populated] 
                                else []

maxBarrels xs = allDivided maxNumBarrels where
  maxNumBarrels = min (div (sum xs) 100) (div (length xs) 2)
  allDivided count | count == 0         = []
                   | not (null divided) = divided
                   | otherwise          = allDivided (count - 1)
    where divided = filter ((==count) . length) 
                  . map (filter ((>=100) . sum)) 
                  . map (map snd) 
                  . divide xs $ count

输出:

*Main> maxBarrels [10,15,20,35,55,65]
[[[55,20,15,10],[65,35]],[[55,35,10],[65,20,15]]]

*Main> maxBarrels [99,99,99]
[[[99,99,99]]]

*Main> maxBarrels [99,99,99,10,15,25,35,55,65]
[[[15,10,99],[25,99],[35,99],[65,55]] ...(the first of 144 immediate results)...