Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enumerate all k-partitions of 1d array with N elements?

This seems like a simple request, but google is not my friend because "partition" scores a bunch of hits in database and filesystem space.

I need to enumerate all partitions of an array of N values (N is constant) into k sub-arrays. The sub-arrays are just that - a starting index and ending index. The overall order of the original array will be preserved.

For example, with N=4 and k=2:

[ | a b c d ] (0, 4)
[ a | b c d ] (1, 3)
[ a b | c d ] (2, 2)
[ a b c | d ] (3, 1)
[ a b c d | ] (4, 0)

And with k=3:

[ | | a b c d ] (0, 0, 4)
[ | a | b c d ] (0, 1, 3)
  :
[ a | b | c d ] (1, 1, 2)
[ a | b c | d ] (1, 2, 1)
  :
[ a b c d | | ] (4, 0, 0)

I'm pretty sure this isn't an original problem (and no, it's not homework), but I'd like to do it for every k <= N, and it'd be great if the later passes (as k grows) took advantage of earlier results.

If you've got a link, please share.

like image 375
Austin Hastings Avatar asked Dec 30 '10 14:12

Austin Hastings


1 Answers

In order to re-use the prior results (for lesser values of k), you can do recursion.

Think of such partitioning as a list of ending indexes (starting index for any partition is just the ending index of the last partition or 0 for the first one).

So, your set of partitionings are just a set of all arrays of k non-decreasing integers between 0 and N.

If k is bounded, you can do this via k nested loops

for (i[0]=0; i[0] < N; i[0]++) {
    for (i[1]=i[0]; i[1] < N; i[1]++) {
    ...
            for (i[10]=i[9]; i[10] < N; i[10]++) {
                push i[0]==>i[10] onto the list of partitionings.
            }
    ...
    }
}

If k is unbounded, you can do it recursively.

A set of k partitions between indexes S and E is obtained by:

  • Looping the "end of first partition" EFP between S and E. For each value:

    • Recursively find a list of k-1 partitions between EFP and S

    • For each vector in that list, pre-pend "EFP" to that vector.

    • resulting vector of length k is added to the list of results.

Please note that my answer produces lists of end-points of each slice. If you (as your example shows) want a list of LENGTHS of each slice, you need to obtain lengths by subtracting the last slice end from current slice end.

like image 60
DVK Avatar answered Sep 23 '22 23:09

DVK