【问题标题】:How to generate all possible combinations out of a given array如何从给定数组中生成所有可能的组合
【发布时间】:2014-08-05 03:22:40
【问题描述】:

由于人们感到困惑,我再次用代码重写我的问题。

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

现在,我正在使用 if 子句,我只能支持 1 到 4 的 d。

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 等。

【问题讨论】:

  • 我对这个问题本身感到很困惑。
  • 我的建议:做好自己的功课。该练习旨在作为一种学习体验,但让其他人为你做这件事会失败。

标签: java arrays combinations


【解决方案1】:

你可以试试这个

static void moves(ArrayList<Integer> prefix, ArrayList<ArrayList<Integer>> result, int min, int max, int stepSize, int maxLength) {
  if(prefix.size() == maxLength) result.add(prefix);
  else {
    for(int i = min; i <= max; i += stepSize) {
      ArrayList<Integer> newPrefix = new ArrayList<Integer>(prefix);
      newPrefix.add(i);
      moves(newPrefix, result, min, max, stepSize, maxLength);
    }
  }
}

static ArrayList<ArrayList<Integer>> moves(int min, int max, int stepSize, int maxLength) {
  ArrayList<ArrayList<Integer>> result = new ArrayList<>();
  moves(new ArrayList<Integer>(), result, min, max, stepSize, maxLength);
  return result;
}

然后你可以用例如调用它moves(0, 50, 5, 2);

【讨论】:

  • 那么如何使用moves函数的输出呢?为什么是嵌套的ArrayList?它不应该是一个简单的列表,例如: ArrayList ?
  • 您的代码运行良好,但我不确定如何将嵌套的 ArrayList 转换为简单的 ArrayList?我的意思是,如何将 ArrayList> 转换为 ArrayList
  • 您能告诉我们如何转换 ArrayList> --------> ArrayList ???
  • 我以为你想要所有组合,而不仅仅是一个。您如何仅用一个 ArrayList 表示多个组合?
【解决方案2】:

这是你想要的代码:

private static int[][] getPossibleValues(final int[] from, final int[] to, final int step) {
    final int width = from.length;
    final int[][] values = new int[width][];

    for (int idx = 0; idx < width; idx++) {
        values[idx] = makeSequence(from[idx], to[idx], step);
    }

    return values;
}

@SuppressWarnings("boxing")
private static List<Integer[]> getPossibleCombinations(final int[][] values, final Stack<Integer> fixed) {
    final int width = fixed.size();
    if (width == values.length) {
        // System.out.println(fixed);
        return Collections.singletonList(fixed.toArray(new Integer[0]));
    }

    final List<Integer[]> res = new ArrayList<>();
    for (int i = 0; i < values[width].length; i++) {
        fixed.push(values[width][i]);
        res.addAll(getPossibleCombinations(values, fixed));
        fixed.pop();
    }

    return res;
}

private static int[] makeSequence(final int from, final int to, final int step) {
    if (((to < from) && (step > 0)) || ((to > from) && (step < 0))) {
        return new int[] { from };
    }

    final int len = ((to - from) / step) + 1;
    final int[] res = new int[len];

    int cur = from;
    for (int i = 0; i < len; i++) {
        res[i] = cur;
        cur += step;
    }

    return res;
}

你可以按如下方式使用它:

public static void main(final String[] args) {
    final int[] from = new int[] { 0, 0, 0 };
    final int[] to = new int[] { 1, 1, 1 };
    final int step = 1;

    for (final Integer[] ints : getPossibleCombinations(getPossibleValues(from, to, step), new Stack<Integer>())) {
        System.out.println(Arrays.asList(ints));
    }
}

输出:

[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]

奖励,检查参数是否合理:

@SuppressWarnings("boxing")
private static void checkArgs(final List<Integer> init, final List<Integer> target, final int step) {
    if (init.size() != target.size()) {
        throw new IllegalArgumentException("Initial and target arrays must be of the same size.");
    }

    if (step == 0) {
        throw new IllegalArgumentException("The step shouldn't be 0.");
    }

    final boolean increment = step > 0;
    for (int idx = 0; idx < init.size(); idx++) {
        if ((increment && (target.get(idx) < init.get(idx))) || (!increment && (target.get(idx) > init.get(idx)))) {
            throw new IllegalArgumentException(
                                                String
                                                    .format(
                                                            "Inconsistent arguments for elements at the index %s: %s cannot reach %s with increments of %s.",
                                                            idx,
                                                            init.get(idx),
                                                            target.get(idx),
                                                            step));
        }
    }
}

【讨论】:

  • 看来是误会了。
【解决方案3】:

好的,这是一个很好的思考问题,我花了一段时间才弄清楚。
很难在不给出答案的情况下指导您完成它。

通常人们会问“你试过什么代码?”。您应该能够编写一些代码来对数组的一个值进行排列,然后从那里开始工作。

从一些代码开始。

perm(int[] start, int step, int[] max, int[] min)

这就是方法签名的样子吗?你有一个你开始的数组。每一步“跳跃”多远,数组的每个索引都有一个需要考虑的最大值和最小值。

我首先创建了一个int[] copy 的起始数组。当我们增加下一个索引值时,我们需要将原始值复制回来。

递增数组中的第一个元素很容易。 copy[0] += step;。现在我们需要做一些检查。如果该值大于最大值或小于最小值,我们需要重置该值 (copy[position] = start[position];) 并按步递增下一个索引。
然后你会注意到一些在逻辑方面循环的代码。我们还需要检查我们增加的值是否在它的范围内。因此,只需在一个循环中编写该代码,该循环就会考虑到它正在处理的数组中的位置。

从执行您需要的小代码块开始,逐步完成数组并处理边缘情况(当它超过最大值时,超过最小值时,当您完成处理数组时)。

很高兴回答更多问题,但您需要用您拥有的代码示例询问具体问题,所以我不觉得我是在为您编写代码。

【讨论】:

    【解决方案4】:

    以下尝试概括嵌套循环的概念:

    static int[][] permute(int[] initial, int[]min,int[] max,int step){//input parameters
        int dim = initial.length;                     //assume all arrays are equal, should probably check though
        int[] start = new int[dim];                   //array for storing the starting value of each loop
        for (int i = 0; i < dim; i++) {
            start[i] = min[i]+(initial[i]-min[i])%step;//finds the smallest value within the given bounds
        }
        int[] steps = new int[dim];                   //number of iterations of each loop
        int totalElements=1;                          //total elments in result
        for (int i = 0; i < dim; i++) {
            steps[i] = (max[i]-start[i])/step+1;      //computes the number of steps in each dimension on [min,max] inclusive
            totalElements*=steps[i];
        }
    
        int[][] results = new int[totalElements][];//for storing results
        for (int i = 0; i < totalElements; i++) {
            results[i]= new int[dim];
            int temp = i;
            for (int j = 0; j < dim; j++) {
                results[i][j] = start[j] + ((temp%steps[j]) * step);//clever method for looping through the array sand storing the result
                temp/=steps[j];
            }
        }
        return results;
    }
    

    运行

    int[][] result = permute(new int[]{10,5}, new int[]{0,0}, new int[]{50,50}, 5);
    for (int[] i : result)
        System.out.println(Arrays.toString(i));
    

    产生:

    [0, 0]
    [5, 0]
    [10, 0]
    [15, 0]
    [20, 0]
    [25, 0]
    [30, 0]
    [35, 0]
    [40, 0]
    [45, 0]
    [50, 0]
    [0, 5]
    [5, 5]
    [10, 5]
    [15, 5]
    [20, 5]
    [25, 5]
    [30, 5]
    [35, 5]
    [40, 5]
    [45, 5]
    [50, 5]
    [0, 10]
    [5, 10]
    [10, 10]
    [15, 10]
    [20, 10]
    [25, 10]
    [30, 10]
    [35, 10]
    [40, 10]
    [45, 10]
    [50, 10]
    [0, 15]
    [5, 15]
    [10, 15]
    [15, 15]
    [20, 15]
    [25, 15]
    [30, 15]
    [35, 15]
    [40, 15]
    [45, 15]
    [50, 15]
    [0, 20]
    [5, 20]
    [10, 20]
    [15, 20]
    [20, 20]
    [25, 20]
    [30, 20]
    [35, 20]
    [40, 20]
    [45, 20]
    [50, 20]
    [0, 25]
    [5, 25]
    [10, 25]
    [15, 25]
    [20, 25]
    [25, 25]
    [30, 25]
    [35, 25]
    [40, 25]
    [45, 25]
    [50, 25]
    [0, 30]
    [5, 30]
    [10, 30]
    [15, 30]
    [20, 30]
    [25, 30]
    [30, 30]
    [35, 30]
    [40, 30]
    [45, 30]
    [50, 30]
    [0, 35]
    [5, 35]
    [10, 35]
    [15, 35]
    [20, 35]
    [25, 35]
    [30, 35]
    [35, 35]
    [40, 35]
    [45, 35]
    [50, 35]
    [0, 40]
    [5, 40]
    [10, 40]
    [15, 40]
    [20, 40]
    [25, 40]
    [30, 40]
    [35, 40]
    [40, 40]
    [45, 40]
    [50, 40]
    [0, 45]
    [5, 45]
    [10, 45]
    [15, 45]
    [20, 45]
    [25, 45]
    [30, 45]
    [35, 45]
    [40, 45]
    [45, 45]
    [50, 45]
    [0, 50]
    [5, 50]
    [10, 50]
    [15, 50]
    [20, 50]
    [25, 50]
    [30, 50]
    [35, 50]
    [40, 50]
    [45, 50]
    [50, 50]
    

    【讨论】:

    • 能否请您再看一下这个问题,我添加了代码和更多解释。谢谢。
    • @user1728624 函数的输入参数及其类型应该是什么?
    猜你喜欢
    • 1970-01-01
    • 2013-07-30
    • 2022-01-18
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    相关资源
    最近更新 更多