代码片段的时间复杂度是O(k * n ^ 2)吗?

时间:2017-08-28 14:48:58

标签: c++ algorithm time-complexity

我正在解决以下LeetCode问题:

  

给定一个数字字符串,返回该数字可能代表的所有可能的字母组合。下面给出了数字到字母的映射(就像在电话按钮上一样)。

Telephone keypad

我试图了解高度赞成的解决方案的复杂性:

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        std::vector< string > vec;
        if(digits.length()==0)
            return vec;

        std::queue< std::string > ans;
        std::string mapping[]={"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

        ans.push("");                           
        for(int i=0; i<digits.length(); i++)
        {
            int x = (digits[i]-'0');
            while(ans.front().length()==i)
            {
                std::string t=ans.front();
                ans.pop();                      
                for(int j=0; j<mapping[x].length(); j++)
                {
                    ans.push(t+mapping[x][j]);
                    //cout<<t+mapping[x][j]<<"\n";
                }
            }
        }

        std::string val;
        int size=ans.size();
        for(int i=0; i<size; i++)
        {
            val=ans.front();
            ans.pop();
            vec.push_back(val);
        }
        return vec;
    }
};

我的理解如下:

如果n是位数,那么我认为复杂度为O(k*n^2),其中k是映射长度(2 - &gt;&#39; abc&#39 ;,3 - &gt;&#39; def&#39;等等。)

最外层的for循环执行n次。在每次迭代期间,我们访问队列中长度等于i的前端元素(在最坏的情况下为n)。这使它成为O(n^2)。最里面的for循环运行一个固定的次数(等于映射长度,比如说k)。此外,push()操作需要恒定的时间。因此,总复杂度为O(k*n^2)

我的理解是否正确?

2 个答案:

答案 0 :(得分:1)

让我们使用以下符号:

  • n是输入的长度;
  • k是映射的最大长度,在您的情况下为4"pqrs""wxyz");

...映射的长度(mapping中的元素数量)与此处的复杂性无关。

pushpopstd::queue的复杂性为O(1)(因为您使用的是deque)。我将假设字符串的连接是O(1)(实际上不是真的)。​​

平凡的,我们可以看到:

  • 内部for循环始终执行k次迭代;
  • 内部while循环将迭代ans.size()

因此,在外部for循环的每次迭代中,内部for循环的主体被评估k * ans.size()次,ans.size()增长k因子{{1}在每次迭代中,所以你有一个指数行为:

  1. i = 0ans.size() = 1 - k次迭代;
  2. i = 1ans.size() = k - k * k次迭代;
  3. i = 2ans.size() = k * k - k * k * k次迭代;
  4. 在最后一次迭代(i = n - 1)期间,内部for循环的主体将被评估k ^ (n - 1)次,因此总体上将评估此主体:

      

    k + k ^ 2 + k ^ 3 + ... + k ^(n - 1)=(k ^ n - 1)/(k - 1) - 1

    因此内部for循环的评估时间为O(k^n)次,因此此函数的复杂性至少为 O(k^n) - 您需要考虑到连接和复制字符串不是O(1)(在这种特定情况下,您可以计算每次迭代的复杂度,在第i次迭代时基本上是O(i + 1)

    这是一个指数复杂性,比你的多项式O(k.n^2)复杂度要差得多。

答案 1 :(得分:0)

不完全。如果你在寻找一个半数学证明(我们假设这里k是一个常数,例如4,即使它不是常数(可以映射到一个,三个或四个(最差情况)数字):

  1. 对于每个i,我们为所有当前解决方案添加一个字母(具有while条件的pop-push机制确保这一点)。所以:

    一个。 i=0我们为每个映射字符添加1个字母,或者添加k项以回答。

    i=1,弹出每个答案,然后为其添加k个选项。目前已存储k个选项,这些选项已存储在上一次迭代中。所以添加了k^2个项目。

    ℃。你明白了,我们的系列将是k + k ^ 2 + k ^ 3 ... k ^ n

  2. 剩下的就是将我们的系列加在i's之上。如果您忘记了结石检验wikipedia。上述几何系列的总和是:

    K *((K ^(N-1)-1)/(K-1)

  3. 因此复杂度为k^(n-1)k^n。这很糟糕,但是可以预料到,因为这就是键盘应该如何工作 - 这是一个令人难以置信的选择。我愿意下注,这也无法改善(除了不使用最坏情况k等) - 只是因为那是你实际返回的字符串数量。