【问题标题】:Number of ways to choose elements from array if the sum of the group is at least K如果组的总和至少为 K,则从数组中选择元素的方法数
【发布时间】:2017-03-02 23:58:55
【问题描述】:

问题:如果我们给定整数 N、K 和大小为 N 的数组,使得 1

这里是一个例子:N = 4, K=6, array = {1,2,5,4} 答案是 9,因为我们可以通过九种不同的方式从数组中获取元素,并且它们的总和至少为 K,答案是元素(第一个和第三个); (第二和第三); (一、二、三); (第二和第四); (一、二、四); (第一、第三和第四); (第二、第三和第四); (一、二、三、四); (第三和第四)。

我的想法是使用位掩码,我们可以搜索所有组合并选择我们应该采用还是不应该采用,但这具有 O(2^N) 的复杂性,在我们的例子中 N

【问题讨论】:

  • 如果任何元素或元素组合大于 K,那么添加任何元素仍将大于 K,假设所有元素都是正数。在您的示例中,如果您发现第一个和第三个元素符合条件,则自动获得集合 (1st,2nd,3rd), (1st,3rd,4th),(1st, 2nd,3rd,4th)跨度>

标签: arrays algorithm bit


【解决方案1】:

对于这个问题,您可以使用类似于通常用于及时解决子集和问题O(N*2^(N/2)) 的“中间相遇技巧”(并且您将具有相同的复杂性)。

首先,计算第一个N/2 元素的2^N/2 可能总和,并将它们存储起来。对最后的 N/2 元素执行相同操作。

现在按升序对两组进行排序。对n 元素进行排序需要时间O(n log n),所以这是O(N 2^(N/2)) 成本。我们将这两个排序集称为FL(分别代表First 和Last)。

然后,执行以下操作:

设置 res = 0

对于 i 从 0 到 2^(N/2)-1{

在 {0,..,2^(N/2)-1} 中找到最小值 j_i,使得 F[i] + L[j_i] >= K(使用二分法搜索)

如果存在这样的 j_i,则将 res 增加 (2^(N/2) - j_i)

}

返回资源

这个想法是,对于第一个N/2 元素的每个子集,您可以查看有多少种方法可以选择最后一个N/2 元素的子集,以使总和高于K。为此,您只需要在最后一个元素的子集的总和中找到实现此目标的最低值,然后您就知道总和至少一样大的值的子集正是与初始元素组合的子集总和中的子集大于或等于K,并且计算这些很容易,因为您对可能值的数组进行了排序。

P.S : 通过使用最小j_i 的序列使得F[i] + L[j_i] >= K 是非递增序列这一事实,可以进行边际优化。

【讨论】:

    猜你喜欢
    • 2015-02-22
    • 2023-04-03
    • 1970-01-01
    • 2016-07-02
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 2013-01-12
    • 2016-02-02
    相关资源
    最近更新 更多