- 个人主页:我的主页
- 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
目录
前言
本文是学习算法分析中的递归分治思想,并解对于整数划分问题的实战运用。文末对经过分析后的递归策略,用GO语言进行了编码验证。
问题描述
一个正整数可以写成一些正整数的和,也就是指把一个正整数n如下如下形式:
n = n1 + n2 + ... + nk (其中 n1 >= n2 ... >= nk > 0, k >= 1),
最常见的问题就是给定正整数n,求不同数组(n1,n2,…, nk)的数目 p(n)。
问题分析
先来举个例子,以6来举例,有如下划分11种不同的划分,所以p(6)=11。
6;
5+1;
4+2, 4+1+1;
3+3, 3+2+1, 3+1+1+1;
2+2+2, 2+2+1+1, 2+1+1+1+1;
1+1+1+1+1+1;
正整数n的所有不同划分中,将最大加数n1 不大于 m 的情况记为q(n,m),这个称作n的m划分。
我们可以建立如下递归关系。
- (1)q(n, 1) = 1, n>=1 ;
当最大加数n1为1时,也就是1+…+1 = n这一种形式
- (2)q(n, m) = q(n , n), m >= n;
最大加数 n1当然不能大于 n, 所以划分数m >= n时, 也就相当于 n 的 n划分;其中特殊的有 q(1, m) = 1;
- (3) q(n, n) = 1 + q(n, n - 1);
正整数n 的划分 可以分解为 最大加数为 n1 = n的划分和 n1 <= n - 1的划分;此时 n1 = n时,只有一种划分,也就是p(6)中的第一个划分,所以就是这里的加1 。
- (4) q(n, m) = q(n, m - 1) + q(n - m, m), 当 n > m > 1时;
这里是最难理解的。当 n > m > 1时,我们最大加数n1=m和n1 <m分解为两个子问题:
- 一是 最大加数 n1 = m 时,剩下的数就为 n - m,也就是n - m 的 m划分。这里已经假定 n1 = m的情况,即q(n - m, m);
- 二是 最大加数 n1 <= m - 1时,也就是 n 的 m - 1划分,q(n , m - 1);
代码
上面按照递归分治的思想将问题分解成子问题,可以递归解决了,现在用代码实现如下:
package main
import (
"fmt"
)
func q(n int, m int)(res int) {
if((n < 1) || (m < 1)) {
return 0
}
if((n == 1) || (m == 1)) {
return 1
}
if(n < m) {
return q(n, n)
}
if(n == m) {
return 1 + q(n, m - 1)
}
return q(n - m, m) + q(n, m - 1)
}
func main() {
for i:=1; i<30; i++ {
for j:=1; j<i+1; j++ {
fmt.Println("q(",i,",",j ,")=",q(i,j))
}
}
}
结尾
作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!