Java中给定字符的可能组合

时间:2018-11-29 18:12:26

标签: java

我正在执行一项任务,需要查找给定字符的所有可能组合。

这是我的输入字符串:

"{a | b} {c | d} e {f | } g {h | i}"

{}中的字符表示在该位置用竖线|符号分隔的其他可能字符。因此,对于此输入,可能的输出如下:

a c e f g h
a c e g h
b c e f g h
b c e g h
a d e f g h
a d e g h
b d e f g h
b d e g h
a c e f g i
a d e f g i
a d e g i
b c e f g i
b d e f g i
b d e g i

我们如何用Java实现呢?

我尝试使用for循环,但无法弄清楚如何找到所有可能的组合?

更新

尝试使用递归调用,但不起作用:

public static void main(String[] args) {
        String in = "{a|b} {c|d} e {f|} g {h|i}";
        String[] array = in.split(" ");
        for (int i = 0; i < array.length; i++) {
            String data = array[i];
            recursivecall(data);
        }
    }

    private static void recursivecall(String data) {
        if (!data.startsWith("{")) {
            System.out.println(data);
        } else {
            String set = data.replace("{", "").replaceAll("}", "");
            System.out.println("set = " + set);
            String[] elements = set.split("\\|");
            for (int i = 0; i < elements.length; i++) {
                recursivecall(elements[i]);
            }
        }
    }

我得到的输出为:

a
b
c
d
e
f
g
h
i

2 个答案:

答案 0 :(得分:3)

为此最容易使用递归;因此您将编写一个可能会自我调用的方法。逻辑将是这样的。

  • 如果输入不包含任何{字符,则只需直接打印即可。这是您的基本情况。
  • 否则,仅选择一组{ }。如果有嵌套对,则选择其中没有任何{ }集的对。
  • 遍历所选元素,调用您的方法,其中参数是用元素替换集合的结果。

例如,如果您的方法参数为"a{b|c|d}e",则将遍历{}集,然后递归到您的方法三遍-每次参数为"abe",{ {1}}和"ace"

递归将确保为每个"ade"集选择每种可能性。这样可以处理每个集合中任意数量的元素,以及集合的任何级别的嵌套。

答案 1 :(得分:0)

这是您可以执行的操作。我假设只有单个字母和空字符串(例如{f | }的第二部分)才被视为有效变体。不允许使用嵌套括号。

这是非递归解决方案。其中最重要的部分是while方法内的compose()循环。在每次迭代中,它会通过添加输入字符串中给出的下一个可用字符的所有可能组合而获得的变体替换combList列表(其最初仅包含一个空字符串)。请注意,您可以在for循环内交换两个while循环以获得相同的组合集,但顺序不同。

import java.util.*;

public class CharCombinations {
    private final String input;
    private int pos;

    private CharCombinations(String input) {
        this.input = input;
    }

    private String[] checkChoice(String[] choice) {
        String[] chars = new String[choice.length];
        int i = 0;
        for (String s : choice) {
            String t = s.trim();
            switch (t.length()) {
                case 0:
                    break;
                case 1:
                    if (Character.isLetter(t.charAt(0))) // internationalized
                        break;
                default:
                    throw new IllegalArgumentException("Not a letter: " + t);
            }
            chars[i++] = t;
        }
        return chars;
    }

    private String[] nextCharChoice() {
        while (pos < input.length() && input.charAt(pos) == ' ')
            pos++;
        if (pos == input.length())
            return null;
        char c = input.charAt(pos++);
        if (c != '{')
            return checkChoice(new String[]{String.valueOf(c)});
        int closBracePos = input.indexOf('}', pos);
        if (closBracePos < 0)
            throw new IllegalArgumentException("No matching delimiter: "
                + input.substring(--pos));
        String delimChoice = " " + input.substring(pos, closBracePos) + " ";
        if (delimChoice.trim().isEmpty())
            throw new IllegalArgumentException("Empty variants list");
        pos = ++closBracePos;
        return checkChoice(delimChoice.split("\\|"));
    }

    private List<String> compose() {
        List<String> combList = new ArrayList<>(1);
        combList.add("");
        String[] choices;
        while ((choices = nextCharChoice()) != null) {
            List<String> newCombList = new ArrayList<>(combList.size() * choices.length);
            for (String c : choices)
                for (String comb : combList)
                    newCombList.add(comb + c);
            combList = newCombList;
        }
        return combList;
    }

    public static List<String> combinations(String input) {
        return new CharCombinations(input).compose();
    }

    public static void main(String[] args) {
        for (String s : combinations("{a | b} {c | d} e {f | } g {h | i}"))
            System.out.println(s);
    }
}