正整数的划分问题是将一个正整数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)。
解法三:母函数算法