欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

分治法-整数划分(java)

程序员文章站 2022-06-11 08:50:37
...

问题:

将正整数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+"种");
    }
}

运行示例

分治法-整数划分(java)

相关标签: 学校考试