我试图计算我可以分割整数的方法。到目前为止,我想出了以下功能:
def partition(num: Int): Int = {
if(num == 1) return 1
if(num <= 0) return 0
return partition(num-1) + partition(num-(num-1))
}
partition(6) //6 instead of 7
例如:5 -> 4 + 1, 3 + 2, 2 + 2 + 1, 2 + 1 + 1 + 1, 1 + 1 + 1 + 1 + 1
如果num
为1,则返回1,因为我认为partition(1)
就是结束。
也许你可以发现其中的逻辑错误?
答案 0 :(得分:4)
我认为这有效:
def partition(n: Int): Int = {
def inner(n: Int, max: Int): Int =
if (n == 0) 1
else if (n < 0) 0
else ((1 to max) map (x => inner(n - x, x))).sum
if (n == 0) 0
else inner(n, n-1)
}
整数n
可以划分为(n-1) + (any way of partitioning 1)
,(n-2) + (any way of partitioning 2)
,...,1 + (any way of partitioning (n-1))
。但是,为partition(m)
天真地计算m = 1 to n-1
并对结果求和将计算一些分区n
两次的方法,例如1 + (n-1)
和(n-1) + 1
。
我们可以通过将分区视为一个正整数序列i{j} < n
并求n
来解决此问题,并且只考虑 ordered 的序列。 inner
方法具有max
参数,可确保仅考虑i{j} >= i{j+1}
的序列。所以它会考虑例如2 + 1
,但不是1 + 2
。
n == 0
在上面的代码中是一个烦人的边缘情况,因为你实际上不想计算空序列。
答案 1 :(得分:2)
def partition(n: Int): Int = {
def partDecr(n: Int, decr: Int): Int = {
if (n == 0) 1
else if (n < 0 || decr == 0) 0
else partDecr(n - decr, decr) + partDecr(n, decr - 1)
}
partDecr(n, n)
}
请注意,这不是尾递归,可以使用相当多的堆栈空间,但速度太慢并不重要。
答案 2 :(得分:1)
我认为没有“那么简单”的算法来计算你想要的东西。 OP中提出的算法不会出于几个原因(我不会讨论)。
但是我引导你到Wikipedia entry on 'Partition',它还包括一个递归公式。
请注意,这个确切的公式在计算上比OP中提出的算法更复杂,也更复杂。
答案 3 :(得分:1)
我认为它需要另一个参数(可以构成分区的整数,称之为madeOf
)。这样你可以将问题分成2个严格较小的子集。 partition(num, madeOf=(n, n-1, ..., 1))
的计数是
partition(num, madeOf=(n-1, ..., 1))
(所有不包含n的分区)partition(num-n, madeOf(n, n-1, ..., 1))
(所有至少有一个n的分区)然后,您可以使其更加优化,因为madeOf
只能由一个int构建:
def part(num: Int, madeOf: Int): Int =
if (num == 0) 1 // we found a partition!
else if (num < 0) 0 // no partition...
else if (madeOf == 0) 0 // no more ways to make partition
else part(num, madeOf - 1) + // all the partitions that don't contain n
part(num - madeOf, madeOf) // all the partition that contain n
part(5, 4) // 6
答案 4 :(得分:0)
您可以使用以下内部函数 - 您只需要创建一个包含数字&lt;的列表。要分区的号码。例如,您想要分区4,那么intNumber应该是(1,2,3,4)
def partition(number: Int, intNumbers: List[Int]): Int = {
if (number <= 0 || intNumbers.isEmpty)
0
else if ((number-intNumbers.head)==0)
1+partition(number-intNumbers.head,intNumbers)+partition(number,intNumbers.tail)
else
partition(number-intNumbers.head,intNumbers)+partition(number,intNumbers.tail)