【问题标题】:Problem figuring out time and space complexity?计算时间和空间复杂度的问题?
【发布时间】:2021-04-03 04:39:00
【问题描述】:

问题是检查两个字符串是否相互旋转。所以,这是我为它写的函数:

 bool areRotations(string s1, string s2)
        {
            int n1 = s1.length(), n2 = s2.length();
            if (n1 != n2) return 0;
            s1 += s1;
            if (s1.find(s2) != string::npos)
                return 1;
            else
                return 0;
        }

我刚刚检查了s1+s1中是否存在s2,如果存在,那么s1和s2一定是相互旋转的。

我无法弄清楚我的代码的时间和空间复杂度。 我能理解的是它应该是 O(n) 时间复杂度,因为首先将 s1 连接到 s1,我们必须创建 s1 的副本,并且要在 s1 中找到 s2,我们必须遍历,因此时间复杂度为 O(n)。 对于空间,它也应该是 O(n),因为我们正在制作 s1 的副本。 这是正确的吗?

【问题讨论】:

  • 对它的各种 N 值进行基准测试,例如 1、10、100,每次迭代上升 10 倍。您会很快发现这条曲线的形状。
  • 顺便说一下,这看起来 O(N²)。我这么说是因为find 测试可能有点慢,尽管您应该运行这些数字来确定。一旦你击中长度为 N=1e6 的字符串,你就会知道。
  • 提示:为什么要复制?您始终可以与长度的模进行比较。 O(N) 保证是这样的。
  • 我认为是复制,因为在执行 s1+s1 之后,我们必须将其存储回 s1,由于长度加倍,我们必须将整个内容复制到 s1(就像内部实现一样向量)。
  • a[i] == b[(i + n) % l]

标签: c++ performance time-complexity space-complexity


【解决方案1】:

我无法弄清楚我的代码的时间和空间复杂度。 [...] 这是正确的吗?

std::string::length 以恒定时间运行 (since C++11)。比较和连接以线性时间运行。但是整个算法可以在非线性时间内运行。

事实上,C++ 标准实际上并不需要任何特定算法或保证std::string::find 的复杂性。因此,不可能独立于您使用的 STL 实现给出答案。 如果实现是幼稚的或使用著名的 Boyer-Moore 算法,则在您的情况下,最坏情况的时间复杂度可能是 O(n^2)(其中 n 是输入字符串的大小)。这可能发生在像 s1="aaaaaaaaaca"s2="aaaaaaaaaac" 这样的输入上。尽管std::search 提供了更强大的保证,但它不提供任何线性时间运行的搜索算法。为确保线性时间复杂度,您可以使用KMP search algorithm(或更好的变体,如2-way string-matching algorithm)。

因此,使用 KMP 算法,您的解决方案的时间和空间复杂度将为O(n)。这是最佳选择,因为需要读取输入字符串并将其存储在某处(至少在您的实现中)。

【讨论】:

    猜你喜欢
    • 2021-01-23
    • 1970-01-01
    • 2012-08-14
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    相关资源
    最近更新 更多