有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将整数分解为k个部分

我在用java编程,我需要制定一个算法。算法的要求是:

  • 我们有3个整数变量nmk
  • 我们想把n分成k个部分,这样k个部分的总和 等于n,每个部分都是介于1m之间的整数
  • 我们需要所有可能的整数组合

例如,对于输入集:

n = 7; m = 3; k = 4

我们可以制定两种不同的组合:

7 = 2 + 2 + 2 + 1

7 = 3 + 2 + 1 + 1

谢谢大家


共 (3) 个答案

  1. # 1 楼答案

    其思想是一种回溯算法方法(使用递归),您可以减少参数并获得部分解,然后检查是否有正确的解

    public class Problem {
    
        private static void algorithm(int n, int k, int m) {
            algorithmRecursive(Collections.EMPTY_LIST, n, k, m, 1);
        }
    
        private static void algorithmRecursive(List<Integer> partial, int n, int k, int m, int min) {
            if ( (k > 0) ) {
                // Optimization
                if ((n <= k * m) && (n >= k*min)){
                    for (int i = min; i <= Math.min(m, n); i++) {
                        List<Integer> newPartial = new ArrayList<>(partial);
                        newPartial.add(i);
                        algorithmRecursive(newPartial, n - i, k - 1, m, i);
                    }
                }
            } else if (n == 0) {
                // Right solution
                System.out.println(partial);
            }
        }
    
        public static void main(String[] args) {
            algorithm(7,4,3);
        }
    }
    
  2. # 2 楼答案

    要获得“分割数”的计数,可以使用Dynamic Programming,它遵循递归公式:

    D(0,0,j) = 1
    D(x,0,j) = 0     x > 0
    D(x,i,j) = 0     x < 0 or j<0
    D(x,i,j) = D(x-j,i-1,j) + D(x,i,j-1)
    

    D(n,k,m)表示的答案是这样的划分的数量。
    复杂性是O(n*k*m)

    Java代码:

    public static int numDivisions(int n, int m, int k) {
        int[][][] D = new int[n+1][k+1][m];
        for (int j = 0; j < m; j++) {
            for (int x = 0; x <= n; x++) {
                D[x][0][j] = 0;
            }
            D[0][0][j] = 1;
        }
        for (int i = 1; i <= k; i++) { 
            for (int x = 0; x <= n; x++) {
                for (int j = 0; j < m; j++) {
                    D[x][i][j] = 0;
                    if (j > 0) D[x][i][j] += D[x][i][j-1];
                    if (x-j-1 >=0) D[x][i][j] += D[x-j-1][i-1][j];
                }
            }
        }
        return D[n][k][m-1];
    }
    

    作为旁注,这类似于stars and bars问题,但这里的顺序并不重要,此外,您还有单元格中“星”数的上限

  3. # 3 楼答案

    我相信用递归可以很容易地做到这一点。首先检查是否可以对n进行除法,即n<=m*k && n>=k,如果不能,则返回空数组

    如果它是可除的,则依次从范围[1..m]中选择m',并选择该值作为第一个数字,然后递归地获取参数n'=n-'m, m'=m', k'=k-1的其余值,然后返回所有结果

    递归将仅对n=0k=0成功停止。时间复杂度应与输出的大小相同