Java实现整数划分

整数的划分问题:将正整数n表示成一系列正整数之和,n=n1+n2+…+nk,其中n1>=n2>=…>=nk>=1,k>=1。
举个简单的例子
6的划分:
6;
5+1;
4+2,4+1+1;
3+3,3+2+1,3+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1;

通过写这个例子不难发现其中的递推关系
每个分号为一组,该组最大的加数为m,第三行m=4,在正整数n的所有不同的划分中,将最大加数n1不大于m的划分个数记做q(n,m)。
也就是说我们要求数字几的划分,也就是求q(n,n)
q(6,4)就是下面的这些:
4+2,4+1+1;
3+3,3+2+1,3+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1;

现在来说一下递推关系:
(1)当n=1,或者m=1时,q(n,m)=1
(2)当n<m时,很明显这种是不正确的,我们设m是最大加数,m就只能小于等于n,所以这种情况就等同于q(n,n)
(3)当n=m时,也就是q(n,n),这时如果返回q(n,n)那么就递推不下去了,这时可以举个例子理解一下
q(6,6)就等于q(6,5)加上单独的数字6,在求划分数目也就是这样写:q(6,6)=q(6,5)+1
推广得:q(n,m)=1+q(n,m-1)
(4)这种是用到最多的情况,n>m时,还是举个例子理解
q(6,4)有哪些:
4+2,4+1+1;
3+3,3+2+1,3+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1;
可以将这些分为两部分,一部分是q(6,3),一部分是q(2,4)
q(6,3):
3+3,3+2+1,3+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;
1+1+1+1+1+1;
q(2,4):
4+2,4+1+1;
得到递推公式:q(n,m)=q(n,m-1)+q(n-m,m)
这样是不是就很清晰了,那为什么不把q(2,4)写成q(2,2)呢?也就是q(n,m)=q(n,m-1)+q(n-m,n-m)
再举个例子: q(6,2)=q(6,1)+q(5,2)
如果这块写成了q(6,2)=q(6,1)+q(5,5),很明显最大加数是2,后面式子确出现了q(5,5),这样是错误的,而且会多算很多划分的个数

分析清楚了,代码很简单,就是递归就行了

public class Main_1 {
    public static void main(String[] args) {
        System.out.println(split(6));
    }
    public static int split(int n) {
        return p(n,n);
    }
    public static int p(int n,int m) {
        if(n==1 || m==1) {
            return 1;
        } else if(n<m) {
            return p(n,n);
        } else if(n==m) {
            return p(n,n-1)+1;
        } else if(n>m) {
            return  p(n,m-1) + p(n-m,m);
        }
        return -1;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42220532/article/details/92786004