如何确定此算法的时间和空间复杂度?

时间:2018-08-13 02:03:07

标签: javascript algorithm recursion permutation

在准备即将进行的采访时,我研究了字符串排列问题。 -

问题语句-编写用于生成输入字符串的所有排列的函数。

这是我觉得很好的解决方案。

function getPermutations(string) {

    // base case
    if (string.length <= 1) {
        return new Set(string);
    }

    var allCharsExceptLast = string.slice(0, -1);
    var lastChar = string[string.length - 1];

    // recursive call: get all possible permutations for all chars except last
    var permutationsOfAllCharsExceptLast = getPermutations(allCharsExceptLast);

    // put the last char in all possible positions for each of the above permutations
    var permutations = new Set();
    permutationsOfAllCharsExceptLast.forEach(function(permutationOfAllCharsExceptLast) {
        for (var position = 0; position <= allCharsExceptLast.length; position++) {
            var permutation = permutationOfAllCharsExceptLast.slice(0, position) + lastChar + permutationOfAllCharsExceptLast.slice(position);
            permutations.add(permutation);
        }
    });

    return permutations;
}

即使我了解解决方案(花了我几次尝试和大约一百万个控制台日志),但递归仍使我感到困惑。有人可以帮我分解时间和空间的复杂性吗?

1 个答案:

答案 0 :(得分:3)

让我们考虑一下这个过程。假设我们的字符串长n个字符。首先,我们必须传递字符串中的每个字符(n操作),然后为每个字符递归地生成字符串中其他n-1个字符的排列,从中我们将为每个第二个字符,以递归方式在字符串中生成n-2个字符的置换,依此类推……直到只剩下1个字符。为了计算总时间复杂度,我们将所有这些项相乘(n * (n-1) * (n-2) * ... * 1 = n!),以O(n!)的Big-O表示法获得时间复杂度。

考虑为什么我们将它们相乘,我们可以想到一个更简单的问题,如下所示:如果我们有2条裤子和3件衬衫,则要穿多少种衣服。答案很明显是六个,而我们得到这个结果的原因是,对于每件衬衫,裤子都有两种选择,因此我们将衬衫的数量乘以裤子的数量。

我们可以将此示例转换为简单的字符串,例如单词“ cat”。为了获得每个排列,您的代码首先选择一个字符(选择字符的顺序无关紧要,所以我将首先选择“ c”),然后在其余字符串中找到排列,在这种情况下为“ ”。琐碎的是,只有两个置换是“ at”和“ ta”,因此我们将字符串“ atc”和“ tac”添加到总体置换中。接下来,我们取出“ a”,剩下的String是“ ct”,从中排列是“ ct”和“ tc”。因此,我们在整体排列中添加了“ cta”和“ tca”。最后,当我们取出“ t”时做同样的事情,我们最终以“ ca”和“ ac”作为剩余的排列,因此我们在整体排列中添加了“ cat”和“ act”,就完成了。请注意,在这种情况下它们都是唯一的,但是如果字母重复(例如在“哇”中),则您的算法将重复计算,这是可以的,因为这实际上并没有必要解决。

无论如何,希望对您有所帮助,如果还有其他问题,请发表评论。