繁体   English   中英

将整数除以k个部分

[英]division an integer into k parts

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

  • 我们有3个整数变量nmk ;
  • 我们要划分nk部分,使得总和k -零件等于n和各部分之间的整数1m
  • 我们希望所有可能的组合与允许的整数。

例如,输入集:

n = 7; m = 3; k = 4

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

7 = 2 + 2 + 2 + 1

7 = 3 + 2 + 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);
    }
}

要获得“分区数”的计数,您可以使用动态编程 ,它遵循递归公式:

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];
}

作为旁注,这类似于星星和条形问题 - 但这里的顺序并不重要,此外你还有单元格中“星星”数量的上限。

我相信这可以通过递归轻松完成。 首先检查你是否可以分割n ,即当n<=m*k && n>=k ,如果不是,则返回空数组。

如果它是可分的,则从范围[1..m]连续选择m'并选择它作为第一个数,然后递归得到其余的参数n'=n-'m, m'=m', k'=k-1 ,然后返回所有结果。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM