特定の文字列の順列を見つけようとしていますが、反復を使用したいと思います。私がオンラインで見つけた再帰的な解決策は理解していますが、反復的な解決策に変換することは実際にはうまくいきません。以下にコードを添付しました。私は本当に助けていただければ幸いです:
public static void combString(String s) {
char[] a = new char[s.length()];
//String temp = "";
for(int i = 0; i < s.length(); i++) {
a[i] = s.charAt(i);
}
for(int i = 0; i < s.length(); i++) {
String temp = "" + a[i];
for(int j = 0; j < s.length();j++) {
//int k = j;
if(i != j) {
System.out.println(j);
temp += s.substring(0,j) + s.substring(j+1,s.length());
}
}
System.out.println(temp);
}
}
私の 関連する質問 コメントのフォローアップとして、ここにJava実装があります Counting QuickPerm Algorithm :
public static void combString(String s) {
// Print initial string, as only the alterations will be printed later
System.out.println(s);
char[] a = s.toCharArray();
int n = a.length;
int[] p = new int[n]; // Weight index control array initially all zeros. Of course, same size of the char array.
int i = 1; //Upper bound index. i.e: if string is "abc" then index i could be at "c"
while (i < n) {
if (p[i] < i) { //if the weight index is bigger or the same it means that we have already switched between these i,j (one iteration before).
int j = ((i % 2) == 0) ? 0 : p[i];//Lower bound index. i.e: if string is "abc" then j index will always be 0.
swap(a, i, j);
// Print current
System.out.println(join(a));
p[i]++; //Adding 1 to the specific weight that relates to the char array.
i = 1; //if i was 2 (for example), after the swap we now need to swap for i=1
}
else {
p[i] = 0;//Weight index will be zero because one iteration before, it was 1 (for example) to indicate that char array a[i] swapped.
i++;//i index will have the option to go forward in the char array for "longer swaps"
}
}
}
private static String join(char[] a) {
StringBuilder builder = new StringBuilder();
builder.append(a);
return builder.toString();
}
private static void swap(char[] a, int i, int j) {
char temp = a[i];
a[i] = a[j];
a[j] = temp;
}
List<String> results = new ArrayList<String>();
String test_str = "abcd";
char[] chars = test_str.toCharArray();
results.add(new String("" + chars[0]));
for(int j=1; j<chars.length; j++) {
char c = chars[j];
int cur_size = results.size();
//create new permutations combing char 'c' with each of the existing permutations
for(int i=cur_size-1; i>=0; i--) {
String str = results.remove(i);
for(int l=0; l<=str.length(); l++) {
results.add(str.substring(0,l) + c + str.substring(l));
}
}
}
System.out.println("Number of Permutations: " + results.size());
System.out.println(results);
例:3文字の文字列がある場合(例: 「abc」、以下のようにパーミュレーションを形成できます。
1)最初の文字で文字列を作成します。 「a」とそれを結果に保存します。
char[] chars = test_str.toCharArray();
results.add(new String("" + chars[0]));
2)次に、文字列の次の文字(つまり、「b」)を取得し、それを以前に作成された文字列のすべての可能な位置に挿入します。この時点で結果( "a")には文字列が1つしかないため、そうすると2つの新しい文字列 'ba'、 'ab'が得られます。これらの新しく作成された文字列を結果に挿入し、「a」を削除します。
for(int i=cur_size-1; i>=0; i--) {
String str = results.remove(i);
for(int l=0; l<=str.length(); l++) {
results.add(str.substring(0,l) + c + str.substring(l));
}
}
3)指定された文字列のすべての文字に対して2)を繰り返します。
for(int j=1; j<chars.length; j++) {
char c = chars[j];
....
....
}
これにより、「ba」から「cba」、「bca」、「bac」、「ab」から「cab」、「acb」、「abc」が得られます。
ワークキューを使用すると、この問題に対する洗練された反復ソリューションを作成できます。
static List<String> permutations(String string) {
List<String> permutations = new LinkedList<>();
Deque<WorkUnit> workQueue = new LinkedList<>();
// We need to permutate the whole string and haven't done anything yet.
workQueue.add(new WorkUnit(string, ""));
while (!workQueue.isEmpty()) { // Do we still have any work?
WorkUnit work = workQueue.poll();
// Permutate each character.
for (int i = 0; i < work.todo.length(); i++) {
String permutation = work.done + work.todo.charAt(i);
// Did we already build a complete permutation?
if (permutation.length() == string.length()) {
permutations.add(permutation);
} else {
// Otherwise what characters are left?
String stillTodo = work.todo.substring(0, i) + work.todo.substring(i + 1);
workQueue.add(new WorkUnit(stillTodo, permutation));
}
}
}
return permutations;
}
部分的な結果を保持するヘルパークラスは非常に単純です。
/**
* Immutable unit of work
*/
class WorkUnit {
final String todo;
final String done;
WorkUnit(String todo, String done) {
this.todo = todo;
this.done = done;
}
}
上記のコードをこのクラスでラップすることでテストできます。
import Java.util.*;
public class AllPermutations {
public static void main(String... args) {
String str = args[0];
System.out.println(permutations(str));
}
static List<String> permutations(String string) {
...
}
}
class WorkUnit {
...
}
コンパイルして実行してみてください。
$ javac AllPermutations.Java; Java AllPermutations abcd
以下の実装は、LIFOキューの代わりにFIFO作業スタックを使用することにより、順列のリストを逆の順序で返すように簡単に調整することもできます。
import Java.util.List;
import Java.util.Set;
import Java.util.ArrayList;
import Java.util.HashSet;
public class Anagrams{
public static void main(String[] args)
{
String inpString = "abcd";
Set<String> combs = getAllCombs(inpString);
for(String comb : combs)
{
System.out.println(comb);
}
}
private static Set<String> getAllCombs(String inpString)
{
Set<String> combs = new HashSet<String>();
if( inpString == null | inpString.isEmpty())
return combs;
combs.add(inpString.substring(0,1));
Set<String> tempCombs = new HashSet<String>();
for(char a : inpString.substring(1).toCharArray())
{
tempCombs.clear();
tempCombs.addAll(combs);
combs.clear();
for(String comb : tempCombs)
{
combs.addAll(getCombs(comb,a));
}
}
return combs;
}
private static Set<String> getCombs(String comb, char a) {
Set<String> combs = new HashSet<String>();
for(int i = 0 ; i <= comb.length(); i++)
{
String temp = comb.substring(0, i) + a + comb.substring(i);
combs.add(temp);
//System.out.println(temp);
}
return combs;
}
}
問題への私のアプローチを投稿するだけです:
import Java.util.ArrayDeque;
import Java.util.Queue;
public class PermutationIterative {
public static void main(String[] args) {
permutationIterative("abcd");
}
private static void permutationIterative(String str) {
Queue<String> currentQueue = null;
int charNumber = 1;
for (char c : str.toCharArray()) {
if (currentQueue == null) {
currentQueue = new ArrayDeque<>(1);
currentQueue.add(String.valueOf(c));
} else {
int currentQueueSize = currentQueue.size();
int numElements = currentQueueSize * charNumber;
Queue<String> nextQueue = new ArrayDeque<>(numElements);
for (int i = 0; i < currentQueueSize; i++) {
String tempString = currentQueue.remove();
for (int j = 0; j < charNumber; j++) {
int n = tempString.length();
nextQueue.add(tempString.substring(0, j) + c + tempString.substring(j, n));
}
}
currentQueue = nextQueue;
}
charNumber++;
}
System.out.println(currentQueue);
}
}