正整数的划分问题是将一个正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。请编写至少三种不同的求解算法,并对所编写算法的时间效率进行测试和比较。
解法一:递归算法
解法二:动态规划算法
解法三:母函数算法
,
xmk表示划分中包含了m个k的情况。正整数n的不同划分个数的母函数为:
利用函数G(x)求出xn的系数即可。
算法如下:
Java代码如下:
package integer_division;
public class Integer_division_3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
long startTime = System.currentTimeMillis();
System.out.println(p(120));//打印120的划分种类数
long endTime = System.currentTimeMillis();
System.out.println("程序运行时间:"+(endTime - startTime) + "ms");
}
public static int p(int n) {
int[] c1 = new int[n+1];
int[] c2 = new int[n+1];
for(int i=0; i<=n; i+=1) {
c1[i] = 1;
c2[i] = 0;
}
for(int i=2; i<=n; i+=1) {
for(int j=0; j<=n; j+=1) {
for(int k=0; k+j<=n; k+=i) {
c2[j+k] += c1[j];
}
}
for(int j=0; j<=n; j+=1) {
c1[j] = c2[j];
c2[j] = 0;
}
}
return c1[n];
}
}
对代码进行实例测试的结果如下:((a,b,c)中a表示正整数,b表示划分结果个数,c表示程序的运行时间,单位是毫秒)
(10,42,1)
(30,5604,1)
(50,204226,1)
(70,4087968,1)
(80,15796476,1)
(90,56634173,1)
(100,190569292,1)
(110,607163746,1)
(后面的测试实例划分结果数目过多,故不展示划分结果数目)
(200,-,3)
(300,-,5)
(400,-,6)
(600,-,8)
(800,-,10)
(1000,-,14)
(1200,-,17)
该算法的时间复杂度为O(n2lnn)。