开发者

Stuck with Combination Problem

I'm having a problem w/ my program. I have extracted a set of data and I would like to test if there is a combination for a particular number. For example, I have an array of int, 1 2 3 4 5, I would like to know if there is a combination for 7 maybe, and it must answer yes there is 3 + 4.

I figured out that I need to use the combination formula. So I thought tha开发者_运维问答t the outer loop may go like 5C1..5C2..5C3..etc, starting to "take 1" then "take 2" at a time to find out all the possible combinations. The problem is I'm stuck at how to implement this in actual codes.

I'm not really very good with Math, A defined loop structure would really help.

Thanks a lot in advance!


Here is a method that gets all possible sums from a List of Integers:

public static void getAllPermutations(final List<Integer> data,
    final Set<Integer> holder){

    if(data.isEmpty()){
        return;
    }
    final Integer first = data.get(0);
    if(data.size() > 1){
        getAllPermutations(data.subList(1, data.size()), holder);
        for(final Integer item : new ArrayList<Integer>(holder)){
            holder.add(first.intValue() + item.intValue());
        }
    }
    holder.add(first);
}

Usage:

List<Integer> data = Arrays.asList(1, 2, 3, 4, 5, 6);
Set<Integer> permutations = new TreeSet<Integer>();
getAllPermutations(data, permutations);
System.out.println(permutations);

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]


While this solution won't give you the operands that lead to the sum, it will include anything from 1 to 1 + 2 + 3 + 4 + 5 + 6


There is a simple pseudo polynomial time dynamic programming for this problem, first determine is possible to rich 1 then for sum 2 we have two option, use one of a array items, or use previous founded 1 add up with new element, you can complete this 2 dimensional table upto rich the requested number:

bool findNode( int[] C , int givenNumber) {
 // compute the total sum
 int n = C.Length;
 int N = 0;
 for( int i = 0; i < n; i++ ) N += C[i];
 // initialize the table 
 T[0] = true;
 for( int i = 1; i <= N; i++ ) T[i] = false;
 // process the numbers one by one
 for( int i = 0; i < n; i++ )
  for( int j = N - C[i]; j >= 0; j--)
   if( T[j] ) T[j + C[i]] = true;

 return T[givenNumber];
}

This is O(n*Sum). in fact is enough to check to O(n*given_number).


A quick and dirty solution might be to create a 2D-Array whose index (in both dimensions) is the position of the number in the array and the values are the combinations. Something like this:

//int i[] = { 1, 3, 5}, operation is 'add'
//you have a 3x3 array here:
//\ |1 3 5    <- the original values at their corresponding indices for quick reference, the array is the bottom right 3x3 matrix
//--+------
//1 |2 4 6    
//3 |4 6 8
//5 |6 8 10

int[][] a = new int[3][3];
//in a loop fill the array

If you now want to find the combinations for 6, you could check all values and get the x and y indices for values that are equal to 6. (In the example: 0/2, 1/1 and 2/0). Then lookup the numbers at those indices in the original array (e.g. 0/2 -> 1 and 5, 1/1 -> 3 and 3, 2/0 -> 5 and 1).

Note that this is a quick and quite imperformant way (especially for bigger arrays) and might return more permutations than you want or need (0/2 and 2/0 is the same for operation add). However, this should work for many possible operations, e.g. xy would be different for x=1, y=5 (result: 1) and x=5, y=1 (result: 5).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜