Вывести все возможные строки длиной k, образованные из набора из n символов без повторяющейся структуры - PullRequest
0 голосов
/ 04 июля 2018

Вывести все возможные строки длины k, образованные из набора из n символов - это распространенный вопрос, и у него уже есть решение .

Тем не менее, я надеюсь узнать

Вопрос : Есть ли способ напечатать все возможные строки без повторяющейся структуры?

Примеры повторяющихся структур [k = 3, n = {a, b, c}]:

  1. AAA = BBB = CCC
  2. ABB = ACC = BAA = BCC = CAA = CBB
  3. ABC = ACB = BAC = BCA = CAB = CBA
  4. ABA = ACA = BAB = BCB = CAC = CBC
  5. AAB = AAC = BBA = BBC = CCA = CCB

Например:

Входной сигнал: k=3, n={a,b,c}

Выход:

aaa
aab
aba
abb
abc

Для требования сложности: оно не должно превышать O(n^k).

1 Ответ

0 голосов
/ 05 июля 2018

Вы можете адаптировать существующее решение. Ограничение, которое вам нужно добавить, заключается в том, что символ может появляться в строке только после того, как все остальные символы перед тем, как он появится в списке, появятся хотя бы один раз. Это работает, потому что для каждого набора строк с одинаковой повторяющейся структурой, есть только одна, где первое появление каждого символа находится в порядке, в котором они появляются в списке, так что это та, которую вы выводите. Вы можете применить это ограничение с помощью дополнительного параметра:

static void printAllKLengthRec(char[] set, 
                            String prefix, 
                            int n, int k, int validCount)
{

    // Base case: k is 0, print prefix
    if (k == 0) 
    {
        System.out.println(prefix);
        return;
    }

    // One by one add all valid characters and recursively call for k equals to k-1
    for (int i = 0; i < validCount; ++i)
    {

        // Next character of input added
        String newPrefix = prefix + set[i]; 

        // increment the valid count if all characters up till then have already
        // appeared and there are characters that have not yet appeared
        // (i.e. validCount < n)
        int newValidCount = (i == (validCount - 1)) && (validCount < n) ?
            validCount + 1 :
            validCount;

        // k is decreased, because we have added a new character
        printAllKLengthRec(set, newPrefix, 
                                n, k - 1, newValidCount); 
    }
}

Так, например, если ваш набор {'a', 'b', 'c', 'd'} и validCount равен 3, это означает, что a и b уже появились, и поэтому a или b или c могут быть добавлены в строку. Если вы добавляете c, то увеличиваете значение перед рекурсивным вызовом функции, потому что теперь a и b и c появились хотя бы один раз, и теперь можно добавить d. Если вы добавите a или b, то значение останется прежним.

Для первого символа в перестановке может появиться только первый символ в списке:

static void printAllKLength(char[] set, int k)
{
    int n = set.length; 
    printAllKLengthRec(set, "", n, k, 1);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...