【问题标题】:Generate all possible combinations longer than the length of an array生成长于数组长度的所有可能组合
【发布时间】:2017-08-02 02:15:40
【问题描述】:

我需要从一个字符串数组/数组列表中构建每个长度 L 的组合,其中 L 大于数组长度

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

示例/伪代码:

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

到目前为止,如果请求的组合长度(示例中为 2)大于 Array 长度(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。

【问题讨论】:

  • 难怪它不起作用。 pointX 是什么?
  • pointX 是您要生成的组合的长度,是吗?如果是这样,请将 int n = set.length+2; 更改为 int n = set.length; 并且您应该很好地将 pointX 设置为值 > 3
  • 已经回答了,最好考虑进一步的逻辑stackoverflow.com/questions/4240080/…
  • 您的示例似乎不一致。为什么输出中是 AA,而不是 BB 或 CC?
  • @Tavo 抱歉,忘记解释了,已编辑后

标签: java arrays algorithm recursion


【解决方案1】:

严格来说,这些是排列而不是组合。您正在生成从一组 n 个候选者中选择的 k 个元素的所有排列,并带有替换(或重复)。会有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;               
        }
    }
}

【讨论】:

    【解决方案2】:

    这里有两个问题:

    int n = set.length+2; -> 这是给你的“甜蜜甜蜜”IndexArrayOutOfBoundsException。将其更改为set.length-1。我不知道你为什么决定随机把+2放在那里。

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

    编辑:或者正如@SirRaffleBuffle 建议的那样,只需执行set.length。他的总学分

    【讨论】:

    • 应该只是int n = set.length;
    • @SirRaffleBuffle 你甚至没有给我时间编辑它:D
    【解决方案3】:

    假设您的示例缺少“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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 2011-05-30
      相关资源
      最近更新 更多