生成长度超过数组长度的所有可能组合

时间:2017-08-02 02:15:40

标签: java arrays algorithm recursion

我需要从String Array / ArrayList构建长度为L的每个组合,其中L大于数组长度

我目前有一个递归方法(不是我自己创建的),只要组合比数组短,就会生成String []的每个组合。

示例/ psudoCode:

input (2, {A,B,C}) 
returns {AA, AB, AC, BA, BC, CB, CA}

截至目前,如果请求的组合长度(示例中为2)大于数组长度(4,5,6 ...而不是2),则递归方法会发出甜蜜的 ArrayIndexOutOfBounds 错误。


我需要的是一种方法(递归与否)将返回数组的每个组合,无论组合是否比数组本身长。通过向阵列添加更多字母并交叉我的手指还是有合法的方法来完成此操作会更好吗?谢谢!

这是我一直在使用的方法。如果你知道信誉所在,请说出来,这不是我自己创造的。

public class bizzBam
{
    // Driver method to test below methods
    public static void main(String[] args) {
        System.out.println("First Test");
        String set1[] = {"a", "b","c"};
        printAllKLength(set1, pointX);
    }

    // The method that prints all possible strings of length k.  It is
    //  mainly a wrapper over recursive function printAllKLengthRec()
    static void printAllKLength(String set[], int k) {
        int n = set.length+2;
        printAllKLengthRec(set, "", n, k);
    }

    // The main recursive method to print all possible strings of length k
    static void printAllKLengthRec(String set[], String prefix, int n, int length) {

        // Base case: k is 0, print prefix
        if (length == 0) {
            System.out.println(prefix);
            return;
        }

        // One by one add all characters from set and recursively
        // call for k equals to k-1
        for (int i = 0; i < n; ++i) {

            // Next character of input added
            String newPrefix = prefix + set[i];

            // k is decreased, because we have added a new character
            printAllKLengthRec(set, newPrefix, n, length - 1);
        }
    }
}

(编辑忘了说:) 至少对于这个算法,如果“PointX”大于输入数组的长度,它将返回indexoutofbounds。

3 个答案:

答案 0 :(得分:3)

严格地说,这些是排列而不是组合。您正在生成从一组n个候选中选择的k个元素的所有排列,并替换(或重复)。会有这样的排列。

这是一种非递归解决方案。

public class Permutations
{
    public static void main(String[] args)
    {
        permutationsKN(new String[]{"a",  "b",  "c"}, 4);
    }

    static void permutationsKN(String[] arr, int k)
    {
        int n = arr.length;

        int[] idx = new int[k];
        String[] perm = new String[k];

        while (true)
        {
            for(int i=0; i<k; i++) perm[i] = arr[idx[i]];           
            System.out.println(String.join("", perm));

            // generate the next permutation
            int i = idx.length - 1;
            for (; i >= 0; i--)
            {
                idx[i]++;
                if (idx[i] < n) break;                  
                idx[i] = 0;
            }

            // if the first index wrapped around then we're done
            if (i < 0) break;               
        }
    }
}

答案 1 :(得分:1)

这里有两个问题:

int n = set.length+2; - &gt;这给了你“甜蜜的甜蜜”IndexArrayOutOfBoundsException。将其更改为set.length-1。我不确定你为什么决定随意放置+2

for (int i = 0; i < n; ++i) - &gt;您将从0循环到n。您需要从0循环到n-1

修改:或者@SirRaffleBuffle建议,只需执行set.length。给他的总积分

答案 2 :(得分:0)

假设您的示例缺少“BB”和“CC”,因为它包含“AA”,看起来您想要的就像汽车的里程表,除了代替十位数字,您需要选择字母。对里程表进行建模并不难:

class Odo {
  private final char [] chars;
  private final int [] positions;
  private boolean hasNext;

  Oddo(String chars, int nPositions) {
    this.chars = chars.toCharArray();
    this.positions = new int [nPositions];
    this.hasNext = true;
  }

  boolean hasNext() {
    return hasNext;
  }

  String emitNext() {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < positions.length; ++i) sb.append(chars[positions[i]]);
    for (int i = 0; i < positions.length; ++i) {
      if (++positions[i] < chars.length) {
        hasNext = true;
        return sb.toString();
      }
      positions[i] = 0;
    }
    hasNext = false;
    return sb.toString();
  }
}

这样打电话:

Odo odo = new Odo("AB", 3);
while (odo.hasNext()) {
  System.out.println(odo.emitNext());
}

可生产

AAA
BAA
ABA
BBA
AAB
BAB
ABB
BBB