当前位置: 首页 > 知识库问答 >
问题:

如何将数组划分为N个最小和子集?

高博涉
2023-03-14

如何将整数数组划分为N个子集,使这些子集的和最小?

例如,数组由11个元素组成,我需要其中的6个子集。

{2,1,1,3,4,4,3,2,1,2,3}

子集:<code>{2,1,1,3},{4},}4,3},}3,2},1,2},{3}</code>最小和=7。

另一个答案是:{2,1,1}{3,4}{4}{3,2}{1,2}{3}最小和=7。

注意:在分区时,必须保持数字在原始集合中出现的顺序。

共有1个答案

林意蕴
2023-03-14

一种可能的方法是二进制搜索答案。

我们需要一个过程来检查我们是否可以仅使用等于或小于参数< code>S的和来划分集合。让我们把这个过程称为< code > onlysumsblow(S)。

我们可以使用贪婪的解决方案来实现< code > onlysumsblow(S)。总是在每个子集中添加尽可能多的元素,并在达到大于S的和之前停止(我在这里假设我们没有负元素,这可能会使讨论复杂化)。如果我们不能使用允许的子集数到达序列的末尾,那么和是无效的(太小)。

function onlySumsBelow(S) {
    partitionsUsed = 1;
    currentSum = 0;

    for each value in sequence {
        if (value > S) return false;

        if (currentSum + value > S) {
            // start a new partition
            currentSum = value;  
            partitionsUsed++;   
        } else {
            currentSum += value;
        }
    }

    return partitionsUsed <= N;
}

一旦我们有了唯一的SumsBelow(S)过程,我们就可以对答案进行二叉搜索,从一个间隔开始,该间隔在左端有一个值,确保搜索的答案不低于(例如0),在右端有一个足够大的数字,以确保搜索的答案不在上方(例如,序列中所有数字的总和)。

如果效率不是一个问题,而不是二进制搜索,你可以简单地尝试多个候选答案一个接一个,从一个足够小的值开始,例如所有数字的总和除以N,然后增加一个,直到达到一个精细的解决方案。

备注:问题末尾没有注释(这限制了我们考虑出现在输入中相邻位置的数字子集),这个问题是NP完全的,因为它是分区问题的推广,它只使用两个集合。

 类似资料:
  • 该问题给出了两个输入:数组(arr)和由数组构成子数组的次数(n)。子数组的和应该是奇数 已经很清楚,如果所有的数字都是偶数。奇数和子数组是不可能的。对于奇数和,连续的2个数字应该是奇数+偶数或者偶数+奇数。但我似乎不能把它们分成N个子数组。请帮忙解释一下逻辑。

  • 我一直陷在这个问题中,找不到有效的解决办法。 我有N(高达1000万)说最大100个元素的数组。这些数组包含1-10000的数字。 现在我的问题是将这些数组划分为K个组,这样我就可以最小化所有数组中的重复项,即一个数组包含1,4,10,100,另一个数组包含1100。我希望他们进入同一组,因为这样可以最大限度地减少口是心非。我的问题的两个限制条件如下- > 组中向量的数量应均匀分布。 根据大小以递

  • 问题内容: 想象一下,我有一个这样的JS数组: 我想要的是将该数组拆分为N个较小的数组。例如: 对于Python,我有这个: 对于JS,我可以提出的最佳解决方案是递归函数,但我不喜欢它,因为它既复杂又丑陋。这个内部函数返回一个像这样的数组[1,2,3,null,4,5,6,null,7,8],然后我必须再次循环并手动拆分它。(我的第一次尝试是返回此:[1、2、3,[4、5、6,[7、8、9]]],

  • 所以,更正式地说,我得到了N个数字,需要把它们分成K个组,这些组中没有一个是空的。每组范围的总和需要最小。例如: N = 4,K = 2,输入为{5,3,1,1}。 一种可能的解决方案是 {5,3},{1,1}。范围的总和为 2 ((5-3) (1-1))。 另一种方法是{1,1,3}{5},它也是2((3-1)(单个数字的范围是0)。 范围始终是组中最大数字和最小数字之间的差值。 当我搜索互联网