如何按顺序获得所有组合

时间:2011-04-01 02:38:36

标签: algorithm

例如

Input

2,1,3

Output

1,1,1
1,1,2
1,1,3
2,1,1
2,1,2
2,1,3

3 个答案:

答案 0 :(得分:3)

如果我正确理解了这个问题,那么这应该可行(代码在Haskell中,将以与示例不同的顺序生成结果)

combinations [] = []
combinations [x]
    |x > 0 = [x]:combinations [(x-1)]
    |otherwise = []
combinations (x:xs)
    |x > 0 = (map (\c -> x:c) (combinations xs)) ++ combinations((x-1):xs)
    |otherwise = []

或者这是为了得到它与你给出的顺序相同(也只是一个更好的解决方案)

 combinations' [x] = [[c]|c<-[1..x]]
 combinations' (x:xs) = [c:d|c<-[1..x],d<-combinations' xs]

我需要用“命令式”语言(C,Java等)来产生答案。这是功能语言闪耀的东西。


好的,在Java中也是如此 免责声明:此代码或多或少只是Haskell的直接翻译。它不干净,或最好的做事方式。我没有测试它,或者确实给它足够的想法以确保它是正确的

public List<List<Integer>> combinations(List<Integer> workwith){
    List<List<Integer>> d = new LinkedList<LinkedList<Integer>>();
    if(workwith.size() == 1){
            int max = workwith.get(0);
        for(int i = 1; i=<max;i++){
            List<Integer> toAdd = new LinkedList<Integer>();
            toAdd.add(i);
            d.add(toAdd);
        }
        return d
    }
    Integer max = workwith.remove(0);
    List<List<Integer>> back = combinations(workwith);
    for(int i = 1, i<=max;i++)
        for(List<Integer> b: back){
        List<Integer> toAdd = new LinkedList<Integer>();
            toAdd.add(i);
            toAdd.addAll(b);
            d.add(toAdd)
        }
    }
    return d;
}

答案 1 :(得分:0)

a [] - 是输入向量

int prod = 1;
for (int i = 0; i < a.size(); i++) prod *= a[i];  // find the count of lines in output

for (int i = 0; i < prod; i++){
     vector<int> b;                         // vector of the current output
     for (int j = a.size()-1; j >= 0; j--){ // for each output calculate its values
          b[j] = i % a[j];                  // each value will be between 0 and a[j]  
          i /= a[j];
     }
     for (int j = 0; j < a.size(); j++)     // output it
          cout << b[j] + 1 << " ";
     cout << endl;
}

答案 2 :(得分:0)

这不是最有效的方法,但这是一个C实现:

/* Assumes output is allocated with enough room for 'len' ints. */
/* Generates the 'num'-th combination in 'output'. */
void get_comb_number(int num, int len, int *input, int *output) {
    int i;
    for (i=num-i-1; i >= 0; --i) {
        output[i] = (num % input[i]) + 1;
        num /= input[i];
    }
}

然后你可以从0循环到输入的乘积(对于上面的例子,它将是2*1*3 = 6),为每个调用get_comb_number并打印出每个组合。代码效率稍低,因为它必须为每个组合调用一个函数,并且必须为每个组合执行所有mod和分区,但IMO代码的简单性弥补了它,如果你不需要效率。请注意,组合编号会稍微快速溢出,但假设32位整数,您将花费几分钟时间只生成该点上的所有组合,并且尝试打印它们的时间要长得多。