如何从数组中找到精确的(最小)元素以匹配给定的总和

Posted

技术标签:

【中文标题】如何从数组中找到精确的(最小)元素以匹配给定的总和【英文标题】:How to find exact (minimum) elements from array to match given sum 【发布时间】:2019-09-12 07:53:38 【问题描述】:

我想要一个返回最小元素数组以匹配给定总和的方法

def find_elements arr, sum
  #logic here
end

例子

arr = [10, 10, 20, 20, 30, 40, 50, 60]
find_elements arr, 50 #should return [50]
find_elements arr, 100 #should return [60, 40]

注意:- 如果没有与总和匹配的组合,则找到接近总和且小于总和的最小元素

find_elements arr, 75 #should return [60, 10]

【问题讨论】:

这看起来很像knapsack problem。 @Marek,我不这么认为,因为 OP 想要找到“匹配给定总和的最小元素子数组”(假设存在这样的子数组),与背包问题不同,是 NP 完全的。 @Salil - [60, 10] 或 [60, 40] 如何是子数组? 无论你想要一个方法,不要犹豫它。 @CarySwoveland notexact: '注意:- 如果没有与总和匹配的组合,则找到接近总和且小于总和的最小元素' 【参考方案1】:

只是出于好奇。可能不是性能最好的。

knapsack = ->(arr, sum) do
  arr = arr.reject(&sum.method(:<)).sort.reverse
  (1..arr.size).reduce([]) do |acc, i|
    result =
      arr.combination(i).reduce([]) do |acc, comb|
        curr = comb.sum
        break comb if curr == sum
        (curr > acc.sum and curr < sum) ? comb : acc
      end
    curr = result.sum
    break result if curr == sum
    (curr > acc.sum and curr < sum) ? result : acc
  end
end

烟雾测试。

knapsack.([10, 10, 20, 20, 30, 40, 50, 60], 50)
#⇒ [50]
knapsack.([10, 10, 20, 20, 30, 40, 50, 60], 110)
#⇒ [60, 50]
knapsack.([10, 10, 20, 20, 30, 40, 50, 60], 90)
#⇒ [60, 30]
knapsack.([10, 10, 20, 20, 30, 40, 50, 60], 75)
#⇒ [60, 10]
knapsack.([10, 10, 20, 20, 30, 40, 50, 60], 500)
#⇒ [60, 50, 40, 30, 20, 20, 10, 10]

【讨论】:

谢谢,有什么办法吗?更高效?【参考方案2】:

我尝试了类似以下的方法,效果很好(但不确定我是否遗漏了任何边缘情况)

class Array
  def head_tail
    head, *tail = *self
    [head, tail]
  end
end

def find_elements array, sum
  head, tail = array.head_tail
  return unless head
  if head < sum
    [ head, *find_elements(tail, (sum - head))]
  elsif head == sum
    head
  elsif head > sum
    find_elements(tail, sum)
  end
end

数组元素按降序排列,如array = [60, 50, 40, 30, 20, 20, 10, 10]

【讨论】:

以上是关于如何从数组中找到精确的(最小)元素以匹配给定的总和的主要内容,如果未能解决你的问题,请参考以下文章

如何找到从多个数组中提取的数字的最小总和?

最小唯一数组总和

寻找子集组合以实现给定总和同时保持成本最小的算法

总和至少为 K 的最小数字集

从数组中找到元素的最小绝对和

如何在 Mongoose 中找到与数组字段的最后一个元素与给定查询值匹配的所有文档?