Arrays 获取scala中数组值组合的总和
我知道有一些类似的问题,但似乎仍然没有一个明确的答案,所以我会问它 我有一个Arrays 获取scala中数组值组合的总和,arrays,scala,functional-programming,Arrays,Scala,Functional Programming,我知道有一些类似的问题,但似乎仍然没有一个明确的答案,所以我会问它 我有一个数组,我试图找到正确的值,这些值的总和将等于限制值,或者从任何给定的组合中得到最接近的值(不超过该值) 根据这个答案,我得出以下结论: def getLimitArr(arr: Array[Int], limit: Int): Unit = { scala.util.Sorting.quickSort(arr) // Array(2, 3, 4, 5, 11, 34) var sum
数组
,我试图找到正确的值,这些值的总和将等于限制
值,或者从任何给定的组合中得到最接近的值(不超过该值)
根据这个答案,我得出以下结论:
def getLimitArr(arr: Array[Int], limit: Int): Unit = {
scala.util.Sorting.quickSort(arr) // Array(2, 3, 4, 5, 11, 34)
var sum = 0L
var i = arr.length-1
val arr2 = ArrayBuffer[Integer]()
while (i >= 0 && sum < limit) {
if(sum + arr(i)<=limit) {
sum += arr(i)
arr2 += arr(i)
}
i -= 1 // 6, 5, 4, 3, 2, 1
}
println(arr2.mkString(", ") + " = " + sum)
}
返回:
println(arr2.mkString(", ") + " = " + sum) // 5, 4 = 9
这是好的,但前提是(构成总和的)值可以从低于极限的最高值得出;在这个示例5中,我们可以看到,它与这个数组一起工作。但是如果此数组的限制值为12(getLimitArr(arr,12)
),则它将返回11=11
,而不是使用5+4+3
我已经使用子集完成了这项工作,但是当数组大于10时,我会得到内存堆错误,因为它在能够获得答案之前正在制定所有组合
那么,我们应该如何做到这一点,使用内存效率高、当前格式或利用Scala的函数式编程功能呢?当我们希望在找到第一个正确答案后立即终止时,递归通常很有用
def getLimit(nums: Array[Int], limit: Int): Array[Int] = {
val subset = nums.filter(limit.>=)
if (subset.isEmpty) Array()
else (1 to subset.length).flatMap(subset.combinations)
.find(_.sum == limit)
.fold(getLimit(subset, limit-1))(identity)
}
getLimit(Array(3, 34, 4, 11, 5, 2), 5) // res0: Array[Int] = Array(5)
getLimit(Array(3, 34, 4, 11, 5, 2), 9) // res1: Array[Int] = Array(4, 5)
getLimit(Array(3, 34, 4, 11, 5, 2), 12) // res2: Array[Int] = Array(3, 4, 5)
getLimit(Array(3, 34, 4, 11, 5, 2), 24) // res3: Array[Int] = Array(3, 4, 11, 5)
注意,最后一个加起来是23,因为没有加起来是24
更新
添加了更好的快捷方式,该方法现在是尾部递归的
def getLimit(nums: Array[Int], limit: Int): Array[Int] = {
val subset = nums.filter(limit.>=)
if (subset.sum <= limit) subset
else {
val res = (1 to subset.length).view
.flatMap(subset.combinations)
.find(_.sum == limit)
if (res.isEmpty) getLimit(subset, limit-1)
else res.get
}
}
def getLimit(nums:Array[Int],limit:Int):Array[Int]={
val子集=nums.filter(限制>=)
如果(subset.sum这似乎是背包问题的一个变体,有一个已知的解决方案:它看起来是,但这并不能回答如何使用多个数组值编写一个有效的解决方案,并且不会导致内存堆错误的问题。谢谢,但是使用任意多个数组值;如果没有使用一两个数组值找到解决方案,我们将得到java.lang.OutOfMemoryError:GC开销限制超过了错误。我正在寻找可以处理多达30个数组值的东西。\u这肯定更好,这是一个有价值的答案,但它不能处理30个数组值,我忍不住觉得有一个更精简的解决方案,可以这么说,尽管我认为它不能处理多达30个数组值这可能是最好的选择,因此标记为正确。当然,如果任何人有任何补充,那么这将对其他人有用。谢谢
def getLimit(nums: Array[Int], limit: Int): Array[Int] = {
val subset = nums.filter(limit.>=)
if (subset.sum <= limit) subset
else {
val res = (1 to subset.length).view
.flatMap(subset.combinations)
.find(_.sum == limit)
if (res.isEmpty) getLimit(subset, limit-1)
else res.get
}
}