Java 仅使用一个字符在字符串列表上生成置换
我正在尝试使用一次使用一个字符的字符串列表生成置换。 下面是我想要的输入和输出代码。 我们能简单地迭代吗?。我也没有找到确切的方法Java 仅使用一个字符在字符串列表上生成置换,java,Java,我正在尝试使用一次使用一个字符的字符串列表生成置换。 下面是我想要的输入和输出代码。 我们能简单地迭代吗?。我也没有找到确切的方法 String[] lst = new String[]{"abc", "def", "ghi"}; //Given String[] permutations = new String[]{ //To Generate "adg", "adh", "adi", "aeg", "aeh", "aei",
String[] lst = new String[]{"abc", "def", "ghi"}; //Given
String[] permutations = new String[]{ //To Generate
"adg", "adh", "adi",
"aeg", "aeh", "aei",
"afg", "afh", "afi",
"bdg", "bdh", "bdi",
"beg", "beh", "bei",
"bfg", "bfh", "bfi",
"cdg", "cdh", "cdi",
"ceg", "ceh", "cei",
"cfg", "cfh", "cfi",
};
更新:我不仅仅是在寻找上面列表大小为3的示例。它可以是任何大小,每个字符串可能恰好具有不同的长度
例如:
list=[“ab”、“abc”、“defghi”、“x”、“einsigl”]
您可以按如下方式操作:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
String[] lst = new String[] { "abc", "def", "ghi" };
List<String> list = new ArrayList<>();
for (char a : lst[0].toCharArray()) {
for (char b : lst[1].toCharArray()) {
for (char c : lst[2].toCharArray()) {
list.add(new String(new char[] { a, b, c }));
}
}
}
// Convert to array
String[] permutations = list.toArray(new String[0]);
// Display
System.out.println(Arrays.toString(permutations));
}
}
public static List<String> generatePermutationsRecursiveSlow(String[] words) {
if (words.length == 0)
// base case
return Collections.singletonList("");
else {
// recursive case
// result list
ArrayList<String> permutations = new ArrayList<>();
// split array into item 0 and items [1..end]
String firstWord = words[0];
String[] otherWords = new String[words.length - 1];
System.arraycopy(words, 1, otherWords, 0, words.length - 1);
// recurse to find permutations for items [1..end]
List<String> otherWordsPermutations = generatePermutationsRecursiveSlow(otherWords);
// for each character in the first word
for (char c : firstWord.toCharArray()) {
// for each permutation from the recursive call's results
for (String otherWordsPermutation : otherWordsPermutations) {
// prepend this character onto the permutation and add it to the results
permutations.add(c + otherWordsPermutation);
}
}
return permutations;
}
}
这里有一种方法可以处理任意长度的任意数量的单词(不包括0)
链接到repl.it:在这个答案中,我将介绍我是如何解决这个问题的,以找到一种算法,该算法适用于任意长度的数组,适用于任意长度的单词,并且不要求所有单词的长度都相同 我将首先生成一个递归解,然后将其转换为一个迭代解 回答此类问题的最简单方法是递归地思考: 生成
[]
的所有排列应返回[“”]
生成非空列表的所有排列意味着,对于列表中第一个单词中的每个字母c
,返回列表其余部分前面有c
前缀的所有排列
这可以用Java编写,如下所示:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
String[] lst = new String[] { "abc", "def", "ghi" };
List<String> list = new ArrayList<>();
for (char a : lst[0].toCharArray()) {
for (char b : lst[1].toCharArray()) {
for (char c : lst[2].toCharArray()) {
list.add(new String(new char[] { a, b, c }));
}
}
}
// Convert to array
String[] permutations = list.toArray(new String[0]);
// Display
System.out.println(Arrays.toString(permutations));
}
}
public static List<String> generatePermutationsRecursiveSlow(String[] words) {
if (words.length == 0)
// base case
return Collections.singletonList("");
else {
// recursive case
// result list
ArrayList<String> permutations = new ArrayList<>();
// split array into item 0 and items [1..end]
String firstWord = words[0];
String[] otherWords = new String[words.length - 1];
System.arraycopy(words, 1, otherWords, 0, words.length - 1);
// recurse to find permutations for items [1..end]
List<String> otherWordsPermutations = generatePermutationsRecursiveSlow(otherWords);
// for each character in the first word
for (char c : firstWord.toCharArray()) {
// for each permutation from the recursive call's results
for (String otherWordsPermutation : otherWordsPermutations) {
// prepend this character onto the permutation and add it to the results
permutations.add(c + otherWordsPermutation);
}
}
return permutations;
}
}
这是更好的优化,因为它使用word
参数来避免O(n)
通过修改字符数组来预加字符串。它还引入了参数i
,它是数组的有效开始索引,可以避免复制输入数组的部分
通过使用堆栈(代替调用堆栈)跟踪不同递归调用之间发生变化的变量,可以将其转换为迭代方法:
private static List generatePermutationsIterative(字符串[]字){
//在递归版本中,每个递归函数调用都有自己的本地副本'i'和'j'`
//在这里用两个堆栈来模拟它
ArrayDeque i_stack=新的ArrayDeque(words.length);
ArrayDeque j_stack=新的ArrayDeque(words.length);
i_stack.add(0);
j_叠加(0);
char[]word=新字符[words.length];
ArrayList置换=新的ArrayList();
而(!i_stack.isEmpty()){
int i=i_stack.removeLast();
int j=j_stack.removeLast();
if(i==单词长度){
//基本情况
添加(新字符串(单词));
继续;
}
if(!(j
代码
作为旁注,看看Haskell对这个问题的两行解决方案有多酷(承认它不是迭代的,但它应该有尾部调用优化,使其与迭代解决方案一样快)。只有当你知道你有多少单词时,这不才有效吗?即使你知道这一点,维护它仍然是一项艰巨的工作。我认为你在最后一篇专栏文章中有一个错误(aei、bei和cei翻了一倍)。谢谢你指出,我已经修复了它。
public static List<String> generatePermutationsRecursiveSlow(String[] words) {
if (words.length == 0)
// base case
return Collections.singletonList("");
else {
// recursive case
// result list
ArrayList<String> permutations = new ArrayList<>();
// split array into item 0 and items [1..end]
String firstWord = words[0];
String[] otherWords = new String[words.length - 1];
System.arraycopy(words, 1, otherWords, 0, words.length - 1);
// recurse to find permutations for items [1..end]
List<String> otherWordsPermutations = generatePermutationsRecursiveSlow(otherWords);
// for each character in the first word
for (char c : firstWord.toCharArray()) {
// for each permutation from the recursive call's results
for (String otherWordsPermutation : otherWordsPermutations) {
// prepend this character onto the permutation and add it to the results
permutations.add(c + otherWordsPermutation);
}
}
return permutations;
}
}
public static List<String> generatePermutationsRecursive(String[] words) {
ArrayList<String> permutations = new ArrayList<>();
int wordLen = words.length;
generatePermutationsRecursive(words, permutations, new char[wordLen], 0);
return permutations;
}
public static void generatePermutationsRecursive(String[] words, ArrayList<String> permutations, char[] word, int i) {
if (i == word.length) {
// base case
permutations.add(new String(word));
} else {
for (int j = 0; j < words[i].length(); j++) {
// equivalent of prepending
word[i] = words[i].charAt(j);
// recurse
generatePermutationsRecursive(words, permutations, word, i + 1);
}
}
}
private static List<String> generatePermutationsIterative(String[] words) {
// in the recursive version, each recursive function call would have its own local copy of `i` and `j`
// simulate that here with 2 stacks
ArrayDeque<Integer> i_stack = new ArrayDeque<>(words.length);
ArrayDeque<Integer> j_stack = new ArrayDeque<>(words.length);
i_stack.add(0);
j_stack.add(0);
char[] word = new char[words.length];
ArrayList<String> permutations = new ArrayList<>();
while (!i_stack.isEmpty()) {
int i = i_stack.removeLast();
int j = j_stack.removeLast();
if (i == words.length) {
// base case
permutations.add(new String(word));
continue;
}
if (!(j < words[i].length())) {
// reached end of loop `for (int j = 0; j < words[i].length(); j++)`
continue;
}
// if not reached end of loop `for (int j = 0; j < words[i].length(); j++)` yet,
// then increment `j` and allow next iteration to happen
i_stack.add(i);
j_stack.add(j + 1);
word[i] = words[i].charAt(j);
// recurse
i_stack.add(i + 1);
j_stack.add(0);
}
return permutations;
}