使用动态大小d生成所有可能的组合?

时间:2014-08-06 06:17:57

标签: java arrays

我想让d在这里动态化,即我希望能够在不事先知道d的值的情况下生成所有可能的数组值组合。

现在,我使用if-clause,我只能支持1到4的d。

这些是输入参数:d,max,min和sz。

if( d == 4 )
{
        for( double i = min ; i <= max ; i = i+ sz )
        {
            for( double j = min ; j <= max ; j = j + sz )
            {
                for( double h = min ; h<=max ; h = h + sz )
                {
                    for( double p = min ; p<=max ; p = p + sz )
                    {
                        double[] att = {i, j, h, p};
                    }
                }
            }
        }
}

if( d == 3 )
{
    for( double i = min ; i <= max ; i = i+ sz )
    {
        for( double j = min ; j <= max ; j = j + sz )
        {
            for( double h = min ; h<=max ; h = h + sz )
            {   
                double[] att = {i, j, h};
            }
        }
    }   
}

if( d == 2 )
{
    for( double i = min ; i <= max ; i = i+ sz )
    {
        for( double j = min ; j <= max ; j = j + sz )
        {
            double[] att = {i, j};
        }
    }   
}

if( d == 1 )
{
    for( double i = min ; i <= max ; i = i+ sz )
    {
        double[] att = {i, j};
    }   
}

正如你所看到的,如果我之前不知道d的价值,我就无法做到。

还有一件事,我不想使用任何模板或预定义的类,如List等。

3 个答案:

答案 0 :(得分:1)

递归是你的朋友。对预定义类的限制使代码变得更加丑陋,但它应该完全相同。它的复杂性也非常糟糕(当你递归时,你会制作很多额外的对象),但是如果你真的想要一个可变数量的嵌套循环,这就是你想要的方法。

private static void makeAtt(double min, double max, double sz, int depth, double[] vals){
    //Guard against bad depth
    if (depth < 0) return;
    if (depth == 0){
        System.out.print("{"); 
        for(double d : vals){
            System.out.print(d + " ");
        }
        System.out.print("}\n\n");
    }
    else{
        for(double i = min; i < max; i += sz){
            double[] newVals = new double[vals.length + 1];
            for(int z = 0; z < vals.length; z++) newVals[z] = vals[z];
            newVals[vals.length] = i;
            makeAtt(min, max, sz, depth - 1, newVals);
        }
    }
}

这是一个正在运行的示例:

public static void main(String[] args){
  makeAtt(0, 3, 1, 3, new double[0]);
}

输出:

{0.0 0.0 0.0}

{0.0 0.0 1.0}

{0.0 0.0 2.0}

{0.0 1.0 0.0}

{0.0 1.0 1.0}

{0.0 1.0 2.0}

{0.0 2.0 0.0}

{0.0 2.0 1.0}

{0.0 2.0 2.0}

{1.0 0.0 0.0}

{1.0 0.0 1.0}

{1.0 0.0 2.0}

{1.0 1.0 0.0}

{1.0 1.0 1.0}

{1.0 1.0 2.0}

{1.0 2.0 0.0}

{1.0 2.0 1.0}

{1.0 2.0 2.0}

{2.0 0.0 0.0}

{2.0 0.0 1.0}

{2.0 0.0 2.0}

{2.0 1.0 0.0}

{2.0 1.0 1.0}

{2.0 1.0 2.0}

{2.0 2.0 0.0}

{2.0 2.0 1.0}

{2.0 2.0 2.0}


要注意的事情;我的代码和原始答案实际上都会生成所有可能的排列,而不是组合。如果你想要组合,你应该在递增之前使每个数字从前一个开始,而不是min。感谢递归设置的方式,您所要做的就是将递归调用更改为:

makeAtt(i, max, sz, depth - 1, newVals);

答案 1 :(得分:0)

你会爱上这个。我自己也在努力解决这个问题,经过几个小时的麻烦后设计了以下算法:

// nCr
public static long c(int n, int r) {
    long result = 1;
    for (int i = 1; i <= r; i++) {
        result *= n - (r - i);
        result /= i;
    }
    return result;
}

public static int[] getCombo(int n, int r, long k) {
    int[] result = new int[r];
    int cur = 1;
    long sum = 0;
    while (r > 0) {
        long tot = c(n - cur, r - 1);
        if (sum + tot <= k) {
            sum += tot;
            cur += 1;
        } else {
            result[result.length - r] = cur;
            cur += 1;
            r--;
        }
    }
    return result;
}

public static void main(String[] args) {

    for (int i = 0; i < c(10,3); i++) {
        int[] res = getCombo(10, 3, i);
        System.out.print(i + " : ");
        for (int j : res) System.out.print(j+" ");
        System.out.println();
    }
}

要使用此功能,只需指定要从中选择的元素数(n)和数量(r),以及从0开始的所需组合(k)。这允许您迭代没有将它们全部保存在数组中的组合。

例如,getCombo(10,3,0)会给你[1,2,3]。当然从10中选择3有120种可能性,所以getCombo(10,3,119)会给你[8,9,10]

该算法基于计算以1和2等开头的各种数字组合。

答案 2 :(得分:0)

我的代码与@ Mshnik非常相似,但没有复制,问题是您是否可以在一个地方处理该组合,或者必须一次返回所有组合......

http://ideone.com/uCUVfk

import java.util.*;
import java.lang.*;
import java.io.*;

class Combinations
{

    static void printCombinations( int K, int[] A ) {
        for ( int i = 0; i < A.length; ++i ) {
            printCombinations( K, A, i, new int[K], 0 );
        }
    }

    static void printCombinations( int K, int[] A, int from, int[] curr,  int idx ) {
        if ( from >= A.length ) return;
        if ( idx == K ) { System.out.println( Arrays.toString(curr) ); return; }
        curr[idx] = A[from];
        for ( int i = from + 1; i < A.length; ++i ) {
            printCombinations( K, A, i, curr,  idx + 1 );
        }
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
        // K - elements in combination
        int K = Integer.parseInt( br.readLine() );
        // N - input array size
        int N = Integer.parseInt( br.readLine() );
        StringTokenizer tok = new StringTokenizer( br.readLine() );
        int[] A = new int[N];
        for ( int i = 0; i < N; ++i ) {
            A[i] = Integer.parseInt( tok.nextToken() );
        }
        //System.out.println( "DEBUG: " + Arrays.toString( A ) );
        printCombinations( K, A );
    }
}

完整组合可用的地方

if ( idx == K ) { System.out.println( Arrays.toString(curr) ); return; }

我只是打印它,你可以把它传递给某个方法并处理它......