正整数的划分问题是将一个正整数n表示成一系列正整数之和:n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。请编写至少三种不同的求解算法,并对所编写算法的时间效率进行测试和比较。
解法一:递归算法
解法二:动态规划算法
算法如下:
Java代码如下:
package integer_division; public class Integer_division_2 { public static void main(String[] args) { // TODO Auto-generated method stub long startTime = System.currentTimeMillis(); System.out.println(p1(100));//打印100的划分种类数 long endTime = System.currentTimeMillis(); System.out.println("程序运行时间:"+(endTime - startTime) + "ms"); } public static int p1(int n) { // TODO Auto-generated method stub int[][] q = new int[n+1][n+1]; int i, j; for (i=1; i<=n; i++){ q[1][i]=q[i][1]=1; } for (i=2; i<=n; i++){ for (j=2; j<=n; j++){ if (i<j){ q[i][j]=q[i][i]; } else if(i==j){ q[i][j]=1+q[i][j-1]; } else{ q[i][j] = q[i][j-1]+q[i-j][j]; } } } return q[n][n]; } //p2与p1相比,少占用了2n+1的空间,方法一样 public static int p2(int n) { // TODO Auto-generated method stub int[][] q = new int[n][n]; int i, j; for (i=0; i<n; i++){ q[0][i]=q[i][0]=1; } for (i=1; i<n; i++){ for (j=1; j<n; j++){ if (i<j){ q[i][j]=q[i][i]; } else if(i==j){ q[i][j]=1+q[i][j-1]; } else{ q[i][j] = q[i][j-1]+q[i-j-1][j];//q[i-j-1]是为了与p1中对应的数位置保持一致 } } } return q[n-1][n-1]; } }
对代码进行实例测试的结果如下:((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,-,2)
(300,-,3)
(400,-,4)
(600,-,6)
(800,-,9)
(1000,-,12)
(1200,-,16)
该算法的时间复杂度为O(n2)。
解法三:母函数算法