分治法-整数划分(java)
问题:
将正整数n表示成一系列正整数之和n=n1+n2+…+nk(其中,n1>=n2>=…>=nk>=1,k>=1),求任意正整数n的划分数(n<10)。例如:
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)。那么如何来定义q(n,m)呢?
我们这里讨论的事分治,递归,那么显然这里我们要用到递归。那么如何来分析这个问题呢?
如果要递归,必须有个终结者,用于最后的返回。然后就是n和nk直接的关系。
算法设计
(1)首先我们需找终结者。分析的方法主要以m为特殊值来进行。
m = 1
q(n, 1) = 1, n >= 1;
最大加数小于等于1的划分只有一种, 1 + 1 + 1 + … +1
当m >= n, 由于n的划分中不可能出现,最大加数大于n的情况,所以得出
q(n, m) = q(n, n),m > = n
q(n, n) = q(n, n - 1) + 1, 这个等式也很好理解,q(n, n - 1),表示n排列中最大加数小于等于n - 1,那所有排列中只剩下一个了,就是n本身,也就是表示中的1。
这里需要注意的事q(n, n) = q(n, n -1) + 1的表达式,是在n和m相同情况下成立,这里并没有找到q(n,m)的通用关系,及m < n的时候
(2)寻找n和nk直接的关系
当m < n时,q(n, m)又如何呢,这里表示最大加数小于等于m的所有排列。根据上面的p(6)的例子。我们很容易推导出q(n, m) = q(n, m - 1) + x,而x是什么呢。
比如我们定义n为6,m为4,那么q(6, 4) = q(6, 3) + x, 这里我们知道q(6,4)所有排列中除掉q(6, 3)就剩下,以4开头的排列了。4开头的排列有多少呢?应该是所有2的排列,既所有6 - 4的排列。
这样我们就推导出通用的关系式了,q(n, m) = q(n, m - 1) + q(n - m, m),这个红色的m如何得到的?当然q(n,m)表示小于等于m的组合,那么q(n - m)里面当然不能大于m了。
总结下:
q(n, m) = 1, n = 1, m =1
= q(n, n) n < m
= 1 + q(n, n -1) n = m
= q (n, m - 1) + q(n - m, m) n >m >1
代码如下
import java .util.Scanner;
public class Main{
public static void print(int[]str,int n,int m,int k) {//打印函数
if (n > 0) {
for (int i = n; i >= 1; i--) {//从大的数开始打印
if (m == 0) {
System.out.println();//该数开头的数已经打印完了,换行
k++;
}
if (m == 0 || i <= str[m - 1]) {
str[m] = i;
print(str, n - i, m + 1, k);//递归调用
}
}
} else {
for (int i = 0; i <= m - 1; i++) {
if (i == (m - 1)) {
if (k == (m - 1)) {
System.out.print(str[i]);
} else
System.out.print(str[i] + ",");
}
else {
System.out.print(str[i] + "+");
}
}
}
}
public static int q(int n,int m){
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 q(n,m-1)+1;
return q(n,m-1)+q(n-m,m);
}
public static void main(String[]args){
Scanner sc=new Scanner(System.in);
System.out.println("请输入一个数:");
int n=sc.nextInt();
print(new int[n],n,0,-1);
int result=q(n,n);
System.out.println();
System.out.println("对整数"+n+"的划分一共有:"+result+"种");
}
}
运行示例
上一篇: 维修记实:老康柏BGA焊接维修实录