如果满足所需的时间复杂度,为啥我的代码会超时?
Posted
技术标签:
【中文标题】如果满足所需的时间复杂度,为啥我的代码会超时?【英文标题】:Why did my code timed out if required time complexity is met?如果满足所需的时间复杂度,为什么我的代码会超时? 【发布时间】:2021-03-14 11:14:52 【问题描述】:我尝试解决 CodeWars kata 并遇到超时错误。我在 cmets 中读到代码应该是 O(n) 复杂度。虽然,我的代码实际上是 O(n)。所以,也许我犯了一些错误等等。为什么这不起作用?有人应该解释为什么我的代码比 O(n) 慢吗?
#include <string>
using namespace std;
bool scramble(const std::string& s1, const std::string& s2)
string copy = s1;
int sum = 0;
for (int i=0; i < s2.size(); ++i)
size_t found = copy.find(string(1,s2[i]));
if (found != string::npos)
sum++;
copy.erase(found,1);
if (sum == s2.size())return true;
return false;
【问题讨论】:
erase
和 find
通常具有线性时间复杂度。所以你的复杂性在 O(s1.length()*s2.length())
虽然,我的代码实际上是 O(n)。 -- 不是O(n)
。如果 string
是 1000 个字符,而您在第一个字符上调用 erase
怎么办?被擦除字符前面的所有字符都必须上移一位。如果您使用不同的数据结构,例如std::list<char>
,也许您可以声明O(n)
。
@PaulMcKenzie 感谢您的建议。我会想办法的。
@kirillshvedov -- 什么是“CodeWars kata”?您要解决的问题是什么?
【参考方案1】:
我看到的最大问题是copy.find()
和copy.erase()
比你想象的要贵。它们本质上是 O(n),并且由于它处于 O(n) for 循环中,因此您至少有 O(n^2) 的运行时间。
通过计算字母,您可以完全避免这种情况。下面的代码是 O(3n) --> O(n)。它还通过了所有测试。
#include<string>
#include <array>
bool scramble(const std::string& s1, const std::string& s2)
std::array<int, 26> s1LetterCounts0;
for (auto& i : s1)
++s1LetterCounts[i - 'a'];
for (auto& i : s2)
--s1LetterCounts[i - 'a'];
for (auto& i : s1LetterCounts)
if (i < 0)
return false;
return true;
最后的 if 条件是满足子串要求。 s1
可能包含 s2
不包含的字符,因此 s2
从计数数组中递减的循环可能会留下一些正数,但绝不应该留下负数。
我可能会在性能方面做得更多(合并第 2 和第 3 个循环),但它按原样通过。
【讨论】:
以上是关于如果满足所需的时间复杂度,为啥我的代码会超时?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 ArrayList 没有打印出 Java 所需的输出?