【问题标题】:Print all possible strings of length k formed from set of n characters without repetitive structure打印由 n 个字符组成的所有可能的长度为 k 的字符串,没有重复结构
【发布时间】:2018-12-12 10:43:51
【问题描述】:

打印由 n 个字符组成的所有可能的长度为 k 的字符串是一个常见问题,并且已经有 solution

不过,我希望知道

问题:有没有办法打印所有可能的字符串而不重复结构?

重复结构示例[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)

【问题讨论】:

  • 嗯,是的,有办法做到这一点。如果你花点时间思考一下,你可能会想出 [k=3, n={a,b,c}] 和 [k=4, n={a,b,c,d] 的解决方案}]。从那里,您应该能够开发通用解决方案。试一试。如果您遇到困难,请发布您的代码并寻求帮助。
  • 您能否显示k=3, n={a,b,c,d} 的预期输出?

标签: java algorithm permutation


【解决方案1】:

您可以调整现有的解决方案。您需要添加的限制是,一个字符只能在列表中它之前的所有其他字符至少出现一次之后出现在字符串中。这是有效的,因为对于具有相同重复结构的每组字符串,只有一个字符的第一次出现按照它们在列表中出现的顺序,所以这是您输出的字符。您可以使用额外的参数来强制执行此限制:

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);
}

【讨论】:

    猜你喜欢
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    相关资源
    最近更新 更多