Java 消除递归

Java 消除递归,java,Java,我刚刚看了下面的代码 package test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(final String[] args) { final int sizeA = 3; final int sizeB = 5; final L

我刚刚看了下面的代码

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(final String[] args) {

        final int sizeA = 3;
        final int sizeB = 5;

        final List<int[]> combos = getAllCombinations(sizeA-1, sizeB);

        int counter = 1;
        for(final int[] combo : combos) {
            System.out.println("Combination " + counter);
            System.out.println("--------------");
            for(final int value : combo) {
                System.out.print(value + " ");
            }
            System.out.println();
            System.out.println();
            ++counter;
        }

    }

    private static List<int[]> getAllCombinations(final int maxIndex, final int size) {

        if(maxIndex >= size)
            throw new IllegalArgumentException("The maximum index must be smaller than the array size.");

        final List<int[]> result = new ArrayList<int[]>();

        if(maxIndex == 0) {
            final int[] array = new int[size];
            Arrays.fill(array, maxIndex);
            result.add(array);
            return result;
        }

        //We'll create one array for every time the maxIndex can occur while allowing
        //every other index to appear, then create every variation on that array
        //by having every possible head generated recursively
        for(int i = 1; i < size - maxIndex + 1; ++i) {

            //Generating every possible head for the array
            final List<int[]> heads = getAllCombinations(maxIndex - 1, size - i);

            //Combining every head with the tail
            for(final int[] head : heads) {
                final int[] array = new int[size];
                System.arraycopy(head, 0, array, 0, head.length);
                //Filling the tail of the array with i maxIndex values
                for(int j = 1; j <= i; ++j)
                    array[size - j] = maxIndex;
                result.add(array);
            }

        }

        return result;

    }

}
封装测试;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.List;
公共班机{
公共静态void main(最终字符串[]args){
最终int sizeA=3;
最终int sizeB=5;
最终列表组合=GetAllCombines(sizeA-1,sizeB);
int计数器=1;
for(最终int[]组合:组合){
系统输出打印项次(“组合”+计数器);
System.out.println(“--------------”;
for(最终int值:combo){
系统输出打印(值+“”);
}
System.out.println();
System.out.println();
++计数器;
}
}
私有静态列表getAllCombinations(最终整型maxIndex,最终整型大小){
如果(最大索引>=大小)
抛出新的IllegalArgumentException(“最大索引必须小于数组大小”);
最终列表结果=新建ArrayList();
如果(maxIndex==0){
最终整数[]数组=新整数[大小];
填充(数组,最大索引);
结果.添加(数组);
返回结果;
}
//在允许的情况下,每次maxIndex出现时,我们都将创建一个数组
//每显示一个其他索引,然后在该数组上创建每个变体
//通过递归生成每个可能的头部
对于(int i=1;i对于(int j=1;j这似乎是家庭作业。在不给你代码的情况下,这里有一个想法。调用
getallcombines
,将结果存储在
列表中,然后从该列表中的随机索引返回一个值。正如Howard在对你的问题的评论中指出的,消除递归和返回随机组合是分开的询问。

如果我正确理解了您的代码,您的任务如下:给出长度为
sizeB
的随机数字组合
'0'..'sizeA-1'

  • 组合已排序
  • 每个数字至少出现一次
  • i、 例如,在您的示例中,例如
    [0,0,1,2,2]

    如果您只想使用单个组合,我建议使用另一种算法(伪代码):

    • 随机选择步进位置(例如,对于序列
      [0,0,1,1,2]
      ,将是步进(
      1->2
      )和(
      3->4
      )-我们需要在
      sizeB-1
      位置随机选择
      sizeA-1
      步进
    • 用这个向量计算你的目标组合
    java中的一个快速而肮脏的实现如下所示

    // Generate list 0,1,2,...,sizeB-2 of possible step-positions 
    List<Integer> steps = new ArrayList<Integer>();
    for (int h = 0; h < sizeB-1; h++) {
        steps.add(h);
    }
    
    // Randomly choose sizeA-1 elements
    Collections.shuffle(steps);
    steps = steps.subList(0, sizeA - 1);
    Collections.sort(steps);
    
    // Build result array
    int[] result = new int[sizeB];
    for (int h = 0, o = 0; h < sizeB; h++) {
        result[h] = o;
        if (o < steps.size() && steps.get(o) == h) {
            o++;
        }
    }
    
    //生成可能阶跃位置的列表0,1,2,…,sizeB-2
    列表步骤=新建ArrayList();
    对于(inth=0;h

    注意:这可以进一步优化-第一步生成一个随机排列,然后将其拆分为所需大小。因此,仅出于演示目的,该算法本身可以按所需工作。

    消除递归和作为结果的单一组合是两种不同的(独立的)任务。你想完成哪一项?(或两者都要?)我想返回一个随机组合。但是对于较大的大小,当前的程序可能不是很有效,因此我认为我也需要消除递归。看看或@skaffman是的,但OP实际上想要消除递归。这不是一个家庭作业。我试着做一些类似于main方法的事情类似这样的东西:final List combos=getallcombions(sizeA-1,sizeB);/*int listSize=combos.size();int item=new Random().nextInt(listSize);int i=0;for(final int[]combo:combos){if(i==item)System.out.println(combo);//i=i+1;}*/但它不起作用为什么有if(i==item)?为什么要在for循环中执行?它不会返回任何数组。我认为这是最好的方法,将随机数和列表中的索引位置匹配,但我可能错了……删除if,然后重新运行它。尝试附加调试器,看看它为什么返回空列表。@Howard,你们有可编译的版本吗?I jus我不想看到它是如何运行的。当我试着在我的代码中运行你的时,它不能正常工作。@Pandy实际上,当你指定了
    sizeA
    sizeB
    时,它正在编译。你可以找到完整的可运行版本。@Howard,你如何修改它,使sizeA不再小于sizeB,(如果较小,则复制值)并且返回的数组大小为2 x sizeB?@Pandy“复制值”是什么意思?请确切指定您想要的组合。我的意思是,如果您有[0,1,1,2]。在这种情况下,sizeA