【问题标题】:Split array basing on chunk weight根据块权重拆分数组
【发布时间】:2019-02-05 05:47:03
【问题描述】:

我有一个带有2 <= n <= 100 双打的数组:

A = [a1, a2, ... , an], ai > 0

和一个整数2 <= k <= min(n, 20)。我需要将A 拆分为k 子数组:

B1 = [a1,     a2, ... , ap]
B2 = [ap+1, ap+2, ... , aq]

             ...

Bk = [aw+1, aw+2, ... , an] 

使得每个B 中的总和几乎相等(很难给出严格的定义——我对近似解感兴趣)。

例子:

Input: A = [1, 2, 1, 2, 1], k=2
Output: [[1, 2, 1], [2, 1]] or [[1, 2], [1, 2, 1]]

我尝试了一种概率方法:

  • 来自[1, 2, .., n] 的样本,使用A 作为概率权重

  • 将样本切成分位数以找到好的分区,

但这对于生产来说不够稳定。

tl;dr 这个question 询问关于 2 块划分的问题。我需要k-chunk 分割。

【问题讨论】:

    标签: python python-3.x algorithm approximation


    【解决方案1】:

    计算数组S 的总和。每个块总和应该接近S / K

    然后遍历数组,计算运行总和R。当R+A[i+1] - S/K 大于S/K - R 时,关闭当前块并生成R=0。继续下一个块。

    您还可以补偿累积错误(如果发生),将M 块的总和与M * S / K 进行比较

    最后一种方法的快速编写代码(未彻底检查)

    def chunks(lst, k):
        s = sum(lst)
        sk = s / k
        #sk = max(s / k, max(lst))
        #variant from user2052436 in comments  
        idx = 0
        chunkstart = 0
        r = 0
        res = []
        for m in range(1, k):
            for idx in range(chunkstart, len(lst)):
                km = k -m
                irest = len(lst)-idx
                if((km>=irest) or (2*r+lst[idx]>2*m*sk)) and (idx>chunkstart):
                    res.append(lst[chunkstart:idx])
                    chunkstart = idx
                    break
                r += lst[idx]
        res.append(lst[idx:len(lst)])
        return res
    
    print(chunks([3,1,5,2,8,3,2], 3))
    print(chunks([1,1,1,100], 3))
    
    >>>[[3, 1, 5], [2, 8], [3, 2]]
       [[1, 1], [1], [100]]
    

    【讨论】:

    • 感谢您的精彩 sn-p!这种方法的问题是有时它会失败 - 例如chunks([1, 1, 1, 100], 3) 将返回 2 个子数组,而不是 3 个。
    • 是的,我们必须添加块长度限制(考虑k-mlen-idx比较)
    • 做了这个更正。也许还有其他棘手的案例。
    • 这似乎工作得很好,干得好! (我还没有创建一个失败的测试)
    • 添加了空块检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 2017-05-15
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多