如何找到所有非重叠组合?

时间:2013-02-08 01:13:32

标签: javascript algorithm

我需要找到所有可能的非重叠项目组合,这些项目被分组到存储桶中。可以有任意数量的桶,每个桶可以包含任意数量的桶。有效组合将恰好包含每个存储桶中的1个项目。

bucket   item  start end
========================

      |-- I1     1    5
B1----|-- I2     6    9
      |-- I3    15    20


      |-- I4    6     9
B2----|-- I5    10    14
      |-- I6    14    25


      |-- I7    1     14
B3----|-- I8    26    40
      |-- I9    1     20
      |-- In ...

Bn ...

例如,我们可以做项目1,4,8; 1,5,8; 1,6,8; 2,5,8; 2,6,8; 3,4,8;和3,5,8。

我们可以观察到项目9没有出现在组合中,因为它与桶1中的所有项目重叠,没有任何选项。

如何有效地解决这个问题?我正在浏览器JavaScript中实现它。

1 个答案:

答案 0 :(得分:1)

蛮力方法是生成桶的笛卡尔积,并过滤掉任何无效的。所以,假设你的桶只是项目列表,那就是:

var cp = _.flatten(_.flatten(_.map(B1, function(item1) {
    return _.map(B2, function(item2) {
        return _.map(B3, function(item3) {
            return [item1, item2, item3];
        });
    });
}), true), true);

将为您提供3桶的笛卡尔产品。

_.filter(cp, function(tuple) {
    return !overlaps(item1, item2) && !overlaps(item1, item3) && !(overlaps(item2, item3);
});

将过滤掉您不想要的(给定合适的重叠定义)。

function overlaps(a, b) {
    return a.lower > b.upper || b.lower > a.upper;
}

您可以将过滤器推广到任意数量的间隔,方法是将笛卡尔积转换为递归调用,计算_.first(args)在_.rest(args)的笛卡尔积上的展平展开。

您可以通过生成所有可能的对并将!_.any(pairs, function(pair) { return overlaps.prototype.apply(undefined, pair); });调用来将过滤器推广到任意数量的间隔。