我正在解决一项编程练习,并遇到了一个我无法满意地找到解决方案的问题。 问题如下:
Print all unique integer partitions given an integer as input.
Integer partition is a way of writing n as a sum of positive integers.
代表: 输入= 4 那么输出应该是 输出=
1 1 1 1
1 1 2
2 2
1 3
4
我应该如何考虑解决这个问题? 我想知道使用递归。任何人都可以为我提供这个问题的算法吗? 或暗示解决方案。 对这类问题的任何解释都是受欢迎的。 (我是编程世界的初学者) 谢谢!!
答案 0 :(得分:17)
我会这样接近:
首先,概括问题。您可以定义一个函数
printPartitions(int target, int maxValue, string suffix)
符合规范:
打印目标的所有整数分区,后跟后缀,以便分区中的每个值最多为maxValue
请注意,始终至少有一个解决方案(前提是target和maxValue均为正数),均为1。
您可以递归使用此方法。所以我们首先考虑基本情况:
printPartitions(0, maxValue, suffix)
应该只打印suffix
。
如果target
不是0
,您必须选择:是否使用maxValue
(如果maxValue > target
只有一个选项:请勿使用它) 。如果您不使用它,则应将maxValue
降低1
。
那是:
if (maxValue <= target)
printPartitions(target-maxValue, maxValue, maxValue + suffix);
if (maxValue > 1)
printPartitions(target, maxValue-1, suffix);
结合这一切导致了一个相对简单的方法(在这里用Java编码,我重新排序语句以获得与你描述的完全相同的顺序):
void printPartitions(int target, int maxValue, String suffix) {
if (target == 0)
System.out.println(suffix);
else {
if (maxValue > 1)
printPartitions(target, maxValue-1, suffix);
if (maxValue <= target)
printPartitions(target-maxValue, maxValue, maxValue + " " + suffix);
}
}
您可以简单地将其称为
printPartitions(4, 4, "");
输出
1 1 1 1
1 1 2
2 2
1 3
4
答案 1 :(得分:3)
这是从Heuster's approach松散得出的。
首先,请注意输出的最后一个数字是1,2,2,3,4
。如果最后一个数字为2
,则最后的第二个数字为1,2
。这告诉我,使用for循环从后面生成字符串的递归函数可能是个好主意。
代码本身很简单:
target
,将变量添加到后缀中,从target
中减去它并递归。代码:
private void printPartitions(int target, int max, String suffix)
{
if (target == 0)
System.out.println(suffix);
else
{
for (int i = 1; i <= max && i <= target; i++)
printPartitions(target - i, i, i + " " + suffix);
}
}
来电者功能:
public void printPartitions(int target)
{
printPartitions(target, target, "");
}
答案 2 :(得分:1)
枚举数字 n 的整数分区的过程是递归的。有一个0的分区,空集()。单个分区为1,即集合(1)。有两个分区2,集合(1 1)和(2)。有三个分区3,集合(1 1 1),(1 2)和(3)。有4个分区,4个集合(1 1 1 1),(1 1 2),(1 3),(2 2)和(4)。存在5个分区,即集合(1 1 1 1 1),(1 1 1 2),(1 2 2),(1 1 3),(1 4),(2 3)和(5)。等等。在每种情况下,通过将小于或等于 n 的每个整数 x 添加到由分区形成的所有集合来确定下一个更大的分区集。 n - x ,消除任何重复。
我在my blog以多种语言提供代码。例如,这是我在Scheme中的解决方案:
(define (set-cons x xs)
(if (member x xs) xs
(cons x xs)))
(define (parts n)
(if (zero? n) (list (list))
(let ((xs (list)))
(do ((x 1 (+ x 1))) ((= x n) (cons (list n) xs))
(do ((yss (parts (- n x)) (cdr yss))) ((null? yss))
(set! xs (set-cons (sort < (cons x (car yss))) xs)))))))
> (parts 0)
(())
> (parts 1)
((1))
> (parts 2)
((2) (1 1))
> (parts 3)
((3) (1 1 1) (1 2))
> (parts 4)
((4) (2 2) (1 1 2) (1 1 1 1) (1 3))
> (parts 5)
((5) (2 3) (1 1 3) (1 1 1 1 1) (1 1 1 2) (1 2 2) (1 4))
> (parts 6)
((6) (3 3) (2 2 2) (2 4) (1 1 4) (1 1 2 2) (1 1 1 1 2)
((1 1 1 1 1 1) (1 1 1 3) (1 2 3) (1 5))
答案 3 :(得分:0)
这是一个算法。让我知道你的想法。在python3上测试
def partition(A):
table = [[[1]]] + [None]*(A-1)
for i in range(1,A):
table[i] = [[i+1]]
for k in range(i):
table[i].extend([[i-k]+l for l in table[k] if i-k >= l[0]])
return table[-1]
def print_partition(A):
for i in reversed(partition(A)): print(*i)