【问题标题】:How do I find all non-overlapping combinations?如何找到所有不重叠的组合?
【发布时间】:2013-02-08 01:13:32
【问题描述】:

我需要找到分组到桶中的所有可能的非重叠项目组合。可能有任意数量的桶,每个桶可以包含任意数量的项目。一个有效的组合将恰好包含每个存储桶中的 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 中实现这一点。

【问题讨论】:

  • 您应该解释一下何时以及如何填充桶。
  • 您应该使用区间树来保存每个桶(以及解决它时的部分解决方案)。除此之外,这看起来像是一个 NP 完全问题。
  • @popnoodles:我从一个简单的对象数组开始。 [{ bucket: Bn, id: In, start: x, end: y }, ... ]
  • 我不明白这个问题;在这种情况下,“不重叠”是什么意思?您示例中的 3、4、8 和 2 值是从哪里来的?我在桶的插图中没有看到它们。
  • @G.Bach:不重叠意味着一个项目的开始值和结束值之间的数字范围与另一个项目不重合。例如I1(1-5)和I4(6-9)不重叠,但I1和I7(1-14)在1、2、3、4、5上重叠。示例中的数字指的是项目编号(如I1)。

标签: javascript algorithm


【解决方案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); });,将过滤器推广到任意数量的区间。

【讨论】:

  • 对不起,如果最初在问题中不清楚 - 我不知道提前计算了多少桶。 (桶的数量取决于数据集和用户选择。)
  • 在这种情况下,我需要在继续之前知道这是否是家庭作业。如果这是硬件问题,我已经给了你足够的帮助来解决问题,否则我可以稍后再回来,当我有更多时间并充实将其推广到 n-buckets 所需的递归调用时。
  • 不,现实世界的问题。 (也许我有写教科书的未来?)
  • 没问题。这是一种可以作为算法课作业的问题。稍后我会尝试再看一遍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2022-08-21
  • 2018-07-31
相关资源
最近更新 更多