生成String的所有分区的递归方法

时间:2017-03-11 01:38:44

标签: java string algorithm recursion

我正在尝试使用partitioning的{​​{1}}解决此问题。我们以“abc”为例 有4个String - partitions
我正在尝试编写一个{a,bc}, {ab,c}, {abc}, {a,b,c}.方法来生成recursivepartitions ArrayList,但我很难这样做。非常感谢帮助!

Lists

现在,当我调用此方法时,它会输出

static List<List<String>> partitions = new ArrayList<>();
static List<String> partition = new ArrayList<>();

static void recurse(int size, String str) {
    if (str.length() <= size) {
        return;
    }
    partition.add(str.substring(0, size));
    for (int i = 1; i < str.length(); i++) {
        if (size < str.length())
            recurse(i, str.substring(size));
    }
    partitions.add(partition);
}

而不是[[, a, b, ab], [, a, b, ab], [, a, b, ab], [, a, b, ab]]

,所以我一定做错了什么:

[[a, b, c], [a, bc], [ab, c], [abc]]

2 个答案:

答案 0 :(得分:3)

我认为使用全局变量并不是一个好主意。

递归函数可能会返回分区列表。

因此,请考虑函数的输入和输出

示例:

  

“ABC”

func("ABC") => func("BC") => func("C")

func("C") returns [["C"]]

因此,您可以在“C”前添加“B”或创建分区。

func("BC") returns [["BC"], ["B", "C"]]

然后再用“A”

再做一遍

func("ABC") returns [["ABC"], ["A", "BC"], ["AB", "C"], ["ABC"]]

代码:

static List<List<String>> recursive(String str) {
    List<List<String>> result = new ArrayList<>();

    if (str.length() == 1) {
        result.add(new ArrayList<>());
        result.get(0).add(str);
        return result;
    }

    for (List<String> list : recursive(str.substring(1))) {
        List<String> append = new ArrayList<>(list);
        append.set(0, str.substring(0, 1) + append.get(0));
        List<String> add = new ArrayList<>(list);
        add.add(0, str.substring(0, 1));
        result.add(append);
        result.add(add);
    }
    return result;
}

添加

此外,您的代码只创建一次partition。因此partition中的partitions来自同一参考!

正因为如此,添加或修改partition会影响每个partition

因此,如您所见,所有partition都相同。

由于这些原因,您最好每步创建一个新的ArrayList,而不是使用全局变量。

答案 1 :(得分:3)

另一种选择,如果您更喜欢使用Java 8流而不是传统的迭代:

private Stream<List<String>> partitions(String text) {
    if (text.isEmpty())
        return Stream.of(new ArrayList<>());
    else
        return IntStream.rangeClosed(1, text.length()).boxed()
            .flatMap(i -> partitions(text.substring(i))
                .peek(p -> p.add(0, text.substring(0, i))));
}

例如,partitions("abcde").forEach(System.out::println)将打印字符串的所有分区。

如果您想转换回列表,那么:

List<List<String>> partitions = partitions(text).collect(Collectors.toList());

如果您不熟悉流,则else子句可以解释为:对于介于1和字符串长度(包括)之间的所有数字,从该流向该数字的子字符串流传输所有分区,然后在每个项目的开头将子字符串插入该数字。