division an integer into k parts

1.7k views Asked by At

I'm programming in java and I need to formulate an algorithm. The requirements of the algorithm are:

  • We have 3 Integer variables n, m, k;
  • We want to divide n into k parts so that the sum of the k-parts are equal to n and each part is an integer between 1 and m.
  • We want all possible combinations with the allowed integers.

For example with input set:

n = 7; m = 3; k = 4

we have two different combinations that we can formulate:

7 = 2 + 2 + 2 + 1

and

7 = 3 + 2 + 1 + 1

thank you all.

3

There are 3 answers

0
David Pérez Cabrera On BEST ANSWER

The idea is a backtraking algorithm approach (with recursion), You can decrease parameters and get partials solutions and then check if you have a right solution.

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);
    }
}
0
amit On

To get the count of "number of divisions" you can use Dynamic Programming, that follows the recursive formula:

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)

The answer denoted by D(n,k,m) is the number of such divisions.
Complexity is O(n*k*m)

Java code:

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

As a side note, this is similar to the stars and bars problem - but here order does not matter, and in addition you have upper bound on the number of "stars" in cell.

0
kajacx On

I believe this can be done easily with recursion. First check if you can divide n at all, that is when n<=m*k && n>=k, if not, return empty array.

If it is divisible, successively choose m' from range [1..m] and choose that as first number, then get the rest recursively for parameters n'=n-'m, m'=m', k'=k-1, then return all the result.

Recursion would successfully stop only for n=0 and k=0. Time complexity should be the same as the size of output.