【问题标题】:Find way to separate array so each subarrays sum is less or equal to a number找到分离数组的方法,使每个子数组的总和小于或等于一个数字
【发布时间】:2017-11-29 20:59:40
【问题描述】:

我有一个数学/算法问题。

给定一个数字数组,想办法把它分成5个子数组,使每个子数组的和小于或等于给定的数字。初始数组中的所有数字都必须转到其中一个子数组,并且是一个总和的一部分。

所以算法的输入是: d - 表示每个子数组总和必须小于或等于的数字 A - 表示将被分成不同子数组的数字数组,并将成为一个总和的一部分

算法复杂度必须是多项式的。 谢谢。

【问题讨论】:

  • 这是作业吗?你试过什么?
  • 你能有负值吗?可以修改输入的顺序吗?

标签: arrays algorithm math complexity-theory


【解决方案1】:

如果“子数组”是指“子集”而不是“连续切片”,则不可能找到解决此问题的多项式时间算法(除非 P = NP)。 Partition Problem 是将一个数字列表划分为多个集合,以使两个集合的总和相等。已知它是 NP 完全的。分区问题可以归结为您的问题如下:

假设x1, ..., x_n 是正数,您希望将其划分为 2 个集合,以使它们的总和相等。让d 成为这个共同的总和(这将是xi 的总和除以2)。通过添加d 的三个副本,将x_i 扩展为大小为n+3 的数组A。显然,将A 划分为 5 个子数组以使每个子数组的总和小于或等于 d 的唯一方法是,如果每个子数组的总和实际上等于 d。这又需要 3 个子数组的长度为 1,每个子数组都由数字 d 组成。剩下的 2 个子数组正好是原始 n 数字的一个分区。

另一方面,如果对数字和/或子数组需要有额外的限制,则可能存在多项式解决方案。但是,如果是这样,您应该清楚地说明存在哪些限制。

【讨论】:

    【解决方案2】:

    设置问题: d : 子数组的上限 A : 初始数组

    假设 A 未排序。 (启发式) 算法:

    1.使用标准排序算法对A进行升序排序->O(nlogn)

    2.检查A的最大元素是否大于d ->(constant) 如果是,没有解决方案 如果没有,继续 3.总结A中的所有元素,记为S。检查S/5 > d ->O(n) 如果是,没有解决方案 如果没有,继续

    4.使用贪心法,创建一个新的子数组Asi,将排序后的A中的下一个最大元素aj添加到Asi,使得Asi之和不超过d。从排序的 A 中删除 aj ->O(n)

    1. 重复第4步,直到满足任一条件:

      I.在创建子数组 Asi 时,只剩下 5-i 个元素 在这种情况下,将剩余元素拆分为单独的子数组,完成

      二。 i = 5。创建了 5 个子数组。

    上述算法的边界为 O(nlogn),因此在多项式时间内。

    【讨论】:

    • 但这种启发式方法并不能保证找到解决方案,即使存在解决方案。
    • 为什么这是一个启发式?
    • 除非您刚刚解决了 P=NP(以一种意想不到的方式),否则您的解决方案只能是启发式的。您正在做的事情类似于最适合的装箱算法。沿着这条线的事情并不总是有效。
    • 但对于某些d 来说,唯一可行的解​​决方案是平等。您的解决方案需要适用于所有有可行解决方案的d,而不仅仅适用于有很多松弛的d
    • 最初,我认为这也是一个NP问题。具体来说,我认为它要求解决子集和问题。当我更仔细地阅读。这个问题的约束没有子集和那么严格。子集和要求严格相等。然而,这个问题只需要“每个子数组的总和小于或等于给定的数字”。因此,我认为可以在poly中解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    相关资源
    最近更新 更多