我有两个字符串str1
和str2
。
是否有任何算法可用于使用递归打印出两个字符串的所有交错?
更新
public class Interleave {
private String resultString[] = new String[10];
private String[] interStr(String str1, String str2){
int n = ((Factorial.factorial(str1.length() + str2.length())) / (Factorial.factorial(str1.length()) * Factorial.factorial(str2.length())));
//n is number of interleavings based on (str1.length()+str2.length())! / (str1.length()! * str2.length()!)
if(str1.length() == 0){
resultString[0] = str2;
return resultString;
}
if(str2.length() == 0){
resultString[0] = str1;
return resultString;
}
else{
for(int i = 0; i < n; i++){
resultString[i]= str1.substring(0, 1) + interStr(str1.substring(1), str2.substring(1));
}
}
return resultString;
}
public static void main(String[] args) {
Interleave obj = new Interleave();
obj.interStr("12", "abc");
for(int i = 0; i < obj.resultString.length; i ++){
System.out.println(obj.resultString[i]);
}
}
}
答案 0 :(得分:12)
问题只是询问是否存在问题的递归算法,答案是肯定的。要查找它,请查找基本案例,然后查找“步骤”。
基本情况是两个字符串中的一个为空时:
interleave(s1, "")
= {s1}
interleave("", s2)
= {s2}
请注意参数的顺序并不重要,因为
interleave("ab", "12")
= {“ab12”,“a1b2”,“1ab2”,“a12b”,“1a2b”,“12ab”} = interleave("12", "ab")
因为顺序无关紧要,我们会看一下第一个字符串长度的递归。
好的,让我们看看一个案例如何导致下一个案例。我将使用一个具体的例子,你可以将它概括为实际代码。
interleave("", "abc")
= {“abc”} interleave("1", "abc")
= {“1abc”,“a1bc”,“ab1c”,“abc1”} interleave("12", "abc")
= {“12abc”,“1a2bc”,“1ab2c”,“1abc2”,“a12bc”,“a1b2c”,“a1bc2”,“ab12c”,“ab1c2”“abc12”} < / LI>
因此,每次我们在第一个字符串中添加一个字符时,我们通过将新字符添加到旧结果集中的所有可能位置来形成新的结果集。让我们看看我们如何从第二个结果中形成第三个结果。当我们添加“2”时,第二个结果中的每个元素如何变成第三个结果中的元素?
现在用这种方式看待事情:
虽然一两个例子一般不能证明规则,但在这种情况下,你应该能够推断出规则是什么。你将有一个循环,里面有递归调用。
这实际上与纯函数式编程相比更有趣,但是你用Java标记了这个问题。
希望这对你来说是一个开始。如果你进一步陷入困境,你可以在网上搜索“交错字符串”或“交错列表”。那里有一些解决方案。
修改:
好吧,我刚刚写了傻事!用脚本语言编写这些内容非常有趣,所以我认为看看它在Java中的样子会很棒。没有我想象的那么糟糕!在这里,打包成一个完整的Java应用程序。
import java.util.ArrayList;
import java.util.List;
public class Interleaver {
/**
* Returns a list containing all possible interleavings of two strings.
* The order of the characters within the strings is preserved.
*/
public static List<String> interleave(String s, String t) {
List<String> result = new ArrayList<String>();
if (t.isEmpty()) {
result.add(s);
} else if (s.isEmpty()) {
result.add(t);
} else {
for (int i = 0; i <= s.length(); i++) {
char c = t.charAt(0);
String left = s.substring(0, i);
String right = s.substring(i);
for (String u : interleave(right, t.substring(1))) {
result.add(left + c + u);
}
}
}
return result;
}
/**
* Prints some example interleavings to stdout.
*/
public static void main(String[] args) {
System.out.println(interleave("", ""));
System.out.println(interleave("a", ""));
System.out.println(interleave("", "1"));
System.out.println(interleave("a", "1"));
System.out.println(interleave("ab", "1"));
System.out.println(interleave("ab", "12"));
System.out.println(interleave("abc", "12"));
System.out.println(interleave("ab", "1234"));
}
}
答案 1 :(得分:1)
如果我正确地解释了您的问题 - 您想要两个字符串中所有字符的所有排列,那么以下代码将有所帮助。您将需要编写自己的交换函数,并以某种方式获取两个字符串中所有字符的数组。 该算法将从第i个元素到数组中的第n个元素进行置换。它是在C ++中,我将包含对算法所在位置的引用,但我不记得了。
void getPermutationsR(char characters[], int n, int i)
{
if (i == n)
{
//Output the current permutation
}
else
{
for (int j=i; j<n; j++)
{
swap (characters, i, j);
getPermutationsR(characters, n, i+1);
swap (characters, i, j);
}
}
}
答案 2 :(得分:1)
你现在拥有的是一个良好的开端。问题是它只返回一个字符串,而不是它们的列表。
更改函数以返回字符串列表,然后考虑如何组合多个列表以生成所需的所有输出。
答案 3 :(得分:1)
这是一个使用递归方法的解决方案,也很容易理解
public class Interleave {
public static List<String> interleave(String first, String second){
if(first.length() == 0){
List<String> list = new ArrayList<String>();
list.add(second);
return list;
}
else if(second.length() == 0){
List<String> list = new ArrayList<String>();
list.add(first);
return list;
}
else{
char c1 = first.charAt(0);
List<String> listA = multiply(c1,interleave(first.substring(1),second));
char c2 = second.charAt(0);
List<String> listB = multiply(c2,interleave(first,second.substring(1)));
listA.addAll(listB);
return listA;
}
}
public static List<String> multiply(char c,List<String> list){
List<String> result = new ArrayList<String>();
for(String str : list){
String res = Character.toString(c) + str;
result.add(res);
}
return result;
}
public static void main(String[] args){
System.out.println(interleave("ab", "1234"));
System.out.println(interleave("a", "b"));
System.out.println(interleave("ab", "cd"));
}
}
答案 4 :(得分:0)
以下是解决此问题的更好,更简单的解决方案:
public class Interleaver {
/**
* Returns a list containing all possible interleavings of two strings.
* The order of the characters within the strings is preserved.
*/
public static String s1 = "abc";
public static String s2 = "12";
public static void interleave(int i, int j, String s) {
if (i == s1.length() && j == s2.length()) {
System.out.println("" + s);
}
if (i != s1.length()) {
interleave(i + 1, j, s + s1.charAt(i));
}
if (j != s2.length()) {
interleave(i, j + 1, s + s2.charAt(j));
}
}//Method ends here
/**
* Prints some example interleavings to stdout.
*/
public static void main(String[] args) {
interleave(0, 0, "");
}//Method ends here
}//Class ends here
程序只使用简单的递归调用来查找解决方案。
答案 5 :(得分:0)
这是另一个递归解决方案:
public class Interleaving2 {
public static void main(String[] args) {
String x = "ab";
String y = "CD";
int m = x.length();
int n = y.length();
char[] result = new char[m + n + 1];
interleave(x, y, result, m, n, 0);
}
public static void interleave(String x, String y, char[] result, int m, int n, int i) {
if (m == 0 && n == 0) {
System.out.println(String.valueOf(result));
}
if (m != 0) {
result[i] = x.charAt(0);
interleave(x.substring(1), y, result, m - 1, n, i + 1);
}
if (n != 0) {
result[i] = y.charAt(0);
interleave(x, y.substring(1), result, m, n - 1, i + 1);
}
}
}