Java 递归方法生成字符串的所有分区
我试图用Java 递归方法生成字符串的所有分区,java,string,algorithm,recursion,Java,String,Algorithm,Recursion,我试图用字符串的分区来解决这个问题。让我们以“abc”为例。 有4个分区-{a,bc},{ab,c},{abc},{a,b,c}。 我正试图编写一个递归方法来生成分区到列表的数组列表,但我很难做到这一点。非常感谢您的帮助 static List<List<String>> partitions = new ArrayList<>(); static List<String> partition = new ArrayList<>();
字符串的分区来解决这个问题。让我们以“abc”为例。
有4个分区
-{a,bc},{ab,c},{abc},{a,b,c}。
我正试图编写一个递归
方法来生成分区
到列表
的数组列表
,但我很难做到这一点。非常感谢您的帮助
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,c],[a,bc],[ab,c],[abc]]
,所以我一定是做错了什么:
recurse(0, "abc");
System.out.println(partitions.toString());
我认为使用全局变量不是一个好主意
递归函数可以返回分区列表
所以,考虑函数的输入和输出
示例:
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;
}
“ABC”
func(“ABC”)=>func(“BC”)=>func(“C”)
func(“C”)返回[[“C”]]
因此,您可以在“C”前面附加“B”,或者创建一个分区
func(“BC”)返回[[“BC”]、[“B”、“C”]]
然后用“A”
func(“ABC”)返回[[“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;
}
静态列表递归(字符串str){
列表结果=新建ArrayList();
如果(str.length()==1){
添加(新的ArrayList());
结果.获取(0).添加(str);
返回结果;
}
对于(列表:递归(str.substring(1))){
List append=新的ArrayList(列表);
append.set(0,str.substring(0,1)+append.get(0));
列表添加=新的ArrayList(列表);
add.add(0,str.substring(0,1));
结果。添加(追加);
结果。添加(添加);
}
返回结果;
}
添加:
此外,您的代码只创建一次分区
。所以分区
中的分区
来自同一个引用
因此,添加或编辑分区
会影响每个分区
s
因此,正如您所看到的,所有的分区都是相同的
由于这些原因,您最好在每个步骤中创建新的ArrayList
,而不是使用全局变量。我认为使用全局变量不是一个好主意
递归函数可以返回分区列表
所以,考虑函数的输入和输出
示例:
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;
}
“ABC”
func(“ABC”)=>func(“BC”)=>func(“C”)
func(“C”)返回[[“C”]]
因此,您可以在“C”前面附加“B”,或者创建一个分区
func(“BC”)返回[[“BC”]、[“B”、“C”]]
然后用“A”
func(“ABC”)返回[[“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;
}
静态列表递归(字符串str){
列表结果=新建ArrayList();
如果(str.length()==1){
添加(新的ArrayList());
结果.获取(0).添加(str);
返回结果;
}
对于(列表:递归(str.substring(1))){
List append=新的ArrayList(列表);
append.set(0,str.substring(0,1)+append.get(0));
列表添加=新的ArrayList(列表);
add.add(0,str.substring(0,1));
结果。添加(追加);
结果。添加(添加);
}
返回结果;
}
添加:
此外,您的代码只创建一次分区
。所以分区
中的分区
来自同一个引用
因此,添加或编辑分区
会影响每个分区
s
因此,正如您所看到的,所有的分区都是相同的
由于这些原因,您最好在每个步骤中创建新的ArrayList
,而不是使用全局变量。如果您更喜欢使用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))));
}
如果您不熟悉streams,则可以将else
子句解释为:对于介于1和字符串长度(包括1)之间的所有数字,将该数字的子字符串的所有分区向前流,然后在每个项的开头插入该数字的子字符串。,如果您更喜欢使用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))));
}
如果您不熟悉streams,else
子句可以解释为:对于介于1和字符串长度(包括1)之间的所有数字,将该数字的子字符串的所有分区向前流,然后在每个项目的开头插入该数字的子字符串。您将传入一个大小为3、长度为3的字符串。recurse方法中的第一个检查是返回,如果它们相等。您是正确的,我修复了它,但输出仍然不正确。您正在传入一个大小为3、长度为3的字符串。recurse方法中的第一个检查是返回,如果它们相等。你是正确的,我修复了它,但输出仍然不正确。这也是我的思维过程,但返回对象的递归对我来说非常混乱。代码看起来正确@ikicha的一个小更正是:result.add(newarraylist());它必须是result.add(newarraylist());否则,它将在工作期间投诉compilation@Yohannes是的,你说得对。但是我知道java编译器的最新版本(可能是7+)可以通过类型推断猜测泛型类型,因为我声明List
@ikicha,你说得对,我想我听说可能是在java 8中。不知什么原因,我的java 7编译器无法从实现中猜出类型。这也是我的思考过程,但返回对象的递归对我来说非常混乱。代码看起来正确@ikicha的一个小更正是:result.add(newarraylist());它必须是result.add(newarraylist());否则,它将在工作期间投诉compilation@Yohannes是的,你说得对。但我知道java编译器的最新版本(可能是7+)可以通过类型推断猜测泛型,因为