我正在解决以下LeetCode问题:
给定一个数字字符串,返回该数字可能代表的所有可能的字母组合。下面给出了数字到字母的映射(就像在电话按钮上一样)。
我试图了解高度赞成的解决方案的复杂性:
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)
。
我的理解是否正确?
答案 0 :(得分:1)
让我们使用以下符号:
n
是输入的长度; k
是映射的最大长度,在您的情况下为4
("pqrs"
或"wxyz"
); ...映射的长度(mapping
中的元素数量)与此处的复杂性无关。
push
上pop
和std::queue
的复杂性为O(1)
(因为您使用的是deque
)。我将假设字符串的连接是O(1)
(实际上不是真的)。
平凡的,我们可以看到:
for
循环始终执行k
次迭代; while
循环将迭代ans.size()
。因此,在外部for
循环的每次迭代中,内部for
循环的主体被评估k * ans.size()
次,ans.size()
增长k
因子{{1}在每次迭代中,所以你有一个指数行为:
i = 0
,ans.size() = 1
- k
次迭代; i = 1
,ans.size() = k
- k * k
次迭代; i = 2
,ans.size() = k * k
- k * k * k
次迭代; 在最后一次迭代(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,即使它不是常数(可以映射到一个,三个或四个(最差情况)数字):
对于每个i
,我们为所有当前解决方案添加一个字母(具有while
条件的pop-push机制确保这一点)。所以:
一个。 i=0
我们为每个映射字符添加1个字母,或者添加k
项以回答。
湾i=1
,弹出每个答案,然后为其添加k
个选项。目前已存储k
个选项,这些选项已存储在上一次迭代中。所以添加了k^2
个项目。
℃。你明白了,我们的系列将是k + k ^ 2 + k ^ 3 ... k ^ n
剩下的就是将我们的系列加在i's
之上。如果您忘记了结石检验wikipedia。上述几何系列的总和是:
K *((K ^(N-1)-1)/(K-1)
因此复杂度为k^(n-1)
或k^n
。这很糟糕,但是可以预料到,因为这就是键盘应该如何工作 - 这是一个令人难以置信的选择。我愿意下注,这也无法改善(除了不使用最坏情况k
等) - 只是因为那是你实际返回的字符串数量。