「abc」という文字列があります。文字列を並べ替えるプログラムは (可能であれば Java で) どのように見えるでしょうか?
例えば:
abc
ABC
Abc
aBc
abC
ABc
abC
AbC
「abc」という文字列があります。文字列を並べ替えるプログラムは (可能であれば Java で) どのように見えるでしょうか?
例えば:
abc
ABC
Abc
aBc
abC
ABc
abC
AbC
このような何かがうまくいくはずです:
void printPermutations(String text) {
char[] chars = text.toCharArray();
for (int i = 0, n = (int) Math.pow(2, chars.length); i < n; i++) {
char[] permutation = new char[chars.length];
for (int j =0; j < chars.length; j++) {
permutation[j] = (isBitSet(i, j)) ? Character.toUpperCase(chars[j]) : chars[j];
}
System.out.println(permutation);
}
}
boolean isBitSet(int n, int offset) {
return (n >> offset & 1) != 0;
}
おそらくすでにご存知のように、可能な異なる組み合わせの数は2 ^ nです。ここで、nは入力文字列の長さに等しくなります。
nは理論的にはかなり大きい可能性があるため、2^ nがintなどのプリミティブ型の容量を超える可能性があります。(ユーザーは、すべての組み合わせが印刷を完了するまで数年待たなければならない場合がありますが、それは彼らの仕事です。)
代わりに、ビットベクトルを使用して、可能なすべての組み合わせを保持しましょう。ビット数をnに設定し、それらをすべて1に初期化します。たとえば、入力文字列が「abcdefghij」の場合、初期ビットベクトル値は{1111111111}になります。
すべての組み合わせについて、入力文字列内のすべての文字をループし、対応するビットが1の場合は各文字を大文字に設定し、そうでない場合は小文字に設定する必要があります。次に、ビットベクトルをデクリメントして繰り返します。
たとえば、「abc」の入力の場合、プロセスは次のようになります。
ビット:対応するコンボ:
111 ABC
110 ABc
101 AbC
100 Abc
011 aBC
010 aBc
001 abC
000 abc
再帰的な関数呼び出しではなくループを使用することで、大きな入力文字列でスタックオーバーフロー例外が発生する可能性も回避できます。
実際の実装は次のとおりです。
import java.util.BitSet;
public void PrintCombinations(String input) {
char[] currentCombo = input.toCharArray();
// Create a bit vector the same length as the input, and set all of the bits to 1
BitSet bv = new BitSet(input.length());
bv.set(0, currentCombo.length);
// While the bit vector still has some bits set
while(!bv.isEmpty()) {
// Loop through the array of characters and set each one to uppercase or lowercase,
// depending on whether its corresponding bit is set
for(int i = 0; i < currentCombo.length; ++i) {
if(bv.get(i)) // If the bit is set
currentCombo[i] = Character.toUpperCase(currentCombo[i]);
else
currentCombo[i] = Character.toLowerCase(currentCombo[i]);
}
// Print the current combination
System.out.println(currentCombo);
// Decrement the bit vector
DecrementBitVector(bv, currentCombo.length);
}
// Now the bit vector contains all zeroes, which corresponds to all of the letters being lowercase.
// Simply print the input as lowercase for the final combination
System.out.println(input.toLowerCase());
}
public void DecrementBitVector(BitSet bv, int numberOfBits) {
int currentBit = numberOfBits - 1;
while(currentBit >= 0) {
bv.flip(currentBit);
// If the bit became a 0 when we flipped it, then we're done.
// Otherwise we have to continue flipping bits
if(!bv.get(currentBit))
break;
currentBit--;
}
}
String str = "Abc";
str = str.toLowerCase();
int numOfCombos = 1 << str.length();
for (int i = 0; i < numOfCombos; i++) {
char[] combinations = str.toCharArray();
for (int j = 0; j < str.length(); j++) {
if (((i >> j) & 1) == 1 ) {
combinations[j] = Character.toUpperCase(str.charAt(j));
}
}
System.out.println(new String(combinations));
}
上記のコード スニペットをここで見つけてください。
public class StringPerm {
public static void main(String[] args) {
String str = "abc";
String[] f = permute(str);
for (int x = 0; x < f.length; x++) {
System.out.println(f[x]);
}
}
public static String[] permute(String str) {
String low = str.toLowerCase();
String up = str.toUpperCase();
char[] l = low.toCharArray();
char u[] = up.toCharArray();
String[] f = new String[10];
f[0] = low;
f[1] = up;
int k = 2;
char[] temp = new char[low.length()];
for (int i = 0; i < l.length; i++)
{
temp[i] = l[i];
for (int j = 0; j < u.length; j++)
{
if (i != j) {
temp[j] = u[j];
}
}
f[k] = new String(temp);
k++;
}
for (int i = 0; i < u.length; i++)
{
temp[i] = u[i];
for (int j = 0; j < l.length; j++)
{
if (i != j) {
temp[j] = l[j];
}
}
f[k] = new String(temp);
k++;
}
return f;
}
}