Вам необходимо динамическое программирование или памятка .В любом случае, та же концепция.
Допустим, вы должны разделить s между n.Рекурсивно, это определено так:
def permutations(s: Int, n: Int): List[List[Int]] = n match {
case 0 => Nil
case 1 => List(List(s))
case _ => (0 to s).toList flatMap (x => permutations(s - x, n - 1) map (x :: _))
}
Теперь, это все равно будет медленным, как ад, но здесь есть ловушка ... вам не нужно пересчитывать permutations(s, n)
для чисел, которые вы уже вычислили,Таким образом, вы можете сделать это вместо этого:
val memoP = collection.mutable.Map.empty[(Int, Int), List[List[Int]]]
def permutations(s: Int, n: Int): List[List[Int]] = {
def permutationsWithHead(x: Int) = permutations(s - x, n - 1) map (x :: _)
n match {
case 0 => Nil
case 1 => List(List(s))
case _ =>
memoP getOrElseUpdate ((s, n),
(0 to s).toList flatMap permutationsWithHead)
}
}
И это может быть еще более улучшено, потому что он будет вычислять каждую перестановку.Вам нужно только вычислить каждую комбинацию, а затем переставить , что без повторного вычисления.
Чтобы вычислить каждую комбинацию, мы можем изменить код следующим образом:
val memoC = collection.mutable.Map.empty[(Int, Int, Int), List[List[Int]]]
def combinations(s: Int, n: Int, min: Int = 0): List[List[Int]] = {
def combinationsWithHead(x: Int) = combinations(s - x, n - 1, x) map (x :: _)
n match {
case 0 => Nil
case 1 => List(List(s))
case _ =>
memoC getOrElseUpdate ((s, n, min),
(min to s / 2).toList flatMap combinationsWithHead)
}
}
Выполнениеcombinations(100, 10)
все еще медленный, учитывая только количество комбинаций.Перестановки для каждой комбинации можно получить, просто вызвав .permutation
для комбинации.