Как вы, вероятно, уже знаете, количество возможных различных комбинаций равно 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 а
Используя цикл вместо рекурсивного вызова функции, мы также исключаем возможность возникновения исключения переполнения стека в больших входных строках.
Вот фактическая реализация:
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--;
}
}