Теория
Комбинаторный часто проще выразить с помощью рекурсивных методов (методы, которые сами себя вызывают).
Я думаю, что алгоритм более понятен на примере, поэтомудавайте возьмем String word = hello12
.
Мы будем повторять каждый символ, пока не будет найдена цифра. Первый - 1
. В этот момент мы можем представить, что слово было разделено на две части виртуальным курсором:
hello
находится слева. Мы знаем, что это не изменится. 12
на правой стороне. Каждый символ может быть цифрой и, следовательно, изменяться.
Чтобы извлечь все возможные комбинации, мы хотим:
- Сохранить первую часть слова
- Вычислить все возможные комбинации второй части слова
- Добавить каждую из этих комбинаций к первой части слова
Следующее дерево представляет то, что мыхотите вычислить (корень - первая часть слова, каждая ветвь представляет комбинацию)
hello
├───1
│ ├───2 (-> hello12)
│ └───@ (-> hello1@)
└───!
├───2 (-> hello!2)
└───@ (-> hello!@)
Вы хотите написать алгоритм, который собирает все ветви этого дерева.
Java Code
/! \ Я советую вам попытаться реализовать то, что я описал выше, прежде чем взглянуть на код: вот как мы улучшаем себя!
Вотсоответствующий код Java:
public static void main(String[] args) {
Set<String> combinations = combinate("hello12");
combinations.forEach(System.out::println);
}
public static Set<String> combinate(String word) {
// Will hold all the combinations of word
Set<String> combinations = new HashSet<String>();
// The word is a combination (could be ignored if empty, though)
combinations.add(word);
// Iterate on each word's characters
for (int i = 0; i < word.toCharArray().length; i++) {
char character = word.toCharArray()[i];
// If the character should be replaced...
if (Character.isDigit(character)) {
// ... we split the word in two at the character's position & pay attention not be exceed word's length
String firstWordPart = word.substring(0, i);
boolean isWordEnd = i + 1 >= word.length();
String secondWordPart = isWordEnd ? "" : word.substring(i + 1);
// Here is the trick: we compute all combinations of the second word part...
Set<String> allCombinationsOfSecondPart = combinate(secondWordPart);
// ... and we append each of them to the first word part one by one
for (String string : allCombinationsOfSecondPart) {
String combination = firstWordPart + getSpecialSymbol(character) + string;
combinations.add(combination);
}
}
}
return combinations;
}
Пожалуйста, оставьте комментарий, если вы хотите, чтобы я объяснил алгоритм дальше.