【问题标题】:What is the time/space complexity of this function that calculates the cartesian product of vectors?这个计算向量笛卡尔积的函数的时间/空间复杂度是多少?
【发布时间】:2018-08-07 18:58:20
【问题描述】:

我无法弄清楚这个函数的时间和空间复杂度是多少。

vector<vector<string>> stringCombinations(const vector<vector<string>> &values) {
    vector<vector<string>> results = {{}};

    for(const auto &vec: values) {
        vector<vector<string>> temp;

        for(const auto &r: results) {
            for(const auto &s: vec) {
                temp.push_back(r);
                temp.back().push_back(s);
            }
        }

        results = move(temp);
    }

    for(const auto &row: results) {
        for(const auto &s: row) {
            cout << s << " ";
        }
        cout << endl;
    }

    return results;
}

这个函数只是字符串的笛卡尔积。给定一个字符串向量的向量,它会打印并返回这些字符串的所有组合。

当看到 3 个嵌套循环时,我立即认为它的时间复杂度大致在 O(n3) 的范围内。但是,随着函数继续运行,第二个循环的长度会发生变化。在第一次迭代时,向量中只有一个元素是空向量。在第二次迭代中,它包含长度为 1 的 n 向量,其中 n 是第一个字符串向量的长度。所以我真的不确定这会如何影响事情。

至于空间复杂度,由于用于存储结果的二维向量,我认为它在 O(m*n) 左右。我只是不确定mn 到底是什么。

【问题讨论】:

    标签: time-complexity complexity-theory asymptotic-complexity space-complexity


    【解决方案1】:

    计算n 长度为k 的向量的笛卡尔积的stringCombinations() 函数的复杂度为O(n * k^n)

    v 成为函数stringCombinations() 的参数,让n 表示v.size()。令v1 ... vn 表示v 的元素,令|u|表示向量u中的元素个数。

    函数计算 n 个向量 v1 ... vn 的笛卡尔积。结果向量results 的大小为|v1| * |v2| * .... * |vn|。 results 的每个元素都是一个大小为 n 的向量。令 k 表示 max(|v1|,..., |vn|)。

    现在我们可以估计算法的复杂度了。令 f(i) 表示在第一次循环的第 i 次迭代中第二次循环的迭代次数。然后我们将得到 O(n * f(n) * k) 因为 k 是上受限于第三次循环的迭代次数。

    对于 f(n),我们有以下公式。如果 kivi 中的字符串个数,那么 f(i) = f(i-1) * k(i-1)。由于 f(1) = 1,很容易看出 f(n) = 1 * k1 * ... * k(n-1) = O(k^(n-1))。那么主循环的复杂度就是O(n * k^n)。

    更新于 13.03.2018 让我们在这里更详细地介绍(澄清符号并修复过程中的一些错误)。在第一个循环的每次迭代中,第二个循环都会经过results 向量。在第一次迭代中,它包含 1 个元素 {}。在第二次迭代中,results 的大小等于我们用 k1 表示的第一个元素 values 的大小。在 vec = {s1,s2,...} 的第二次迭代中,每个元素 r={s} 将被替换为 k2 元素。 {s,s1},{s,s2},...,因此第二次迭代后 result 向量的大小将等于 k1 * k2。在每次后续迭代 i 之后,result 的大小将乘以 ki。这个大小将决定第一个循环的下一次迭代中第二个循环的迭代次数。所以 *f(i+1) = 1 * k1 * ... * ki.

    一个例子会很方便。让values = {{"1","2"},{"3","4","5"}}。这里 n = 2。在第一次迭代开始时,我们有

       results = {{}}, vec={"1","2"}, *k1* = 2, *f(1)*=1
    

    在第二次迭代开始时,我们有

       results = {{"1"},{"2"}}, vec={"3","4","5"}, *k2*=3, *f(2)*=2
    

    最后我们有

       results = {{"1","3"},{"1","4"},{"1","5"},
                  {"2","3"},{"2","4"},{"2","5"}}
    

    操作次数为T = f(1) * k1 + f(2) * k2。由于 k = max(k1,k2) = 3,我们有 Tf(1) + f(2)) f(2) *2。 更新结束

    还要注意results中的元素个数是O(n * k^n),所以这也是第二个循环的复杂度.

    如你所说,如果我们让 m = k^n,那么复杂度是 O(m * n )。然而,这种表示法可能会产生误导,因为输入数组可以被视为 n by k 数组,因此最好根据输入的维度给出复杂度估计数组,所以它是 O(n * k^n)。

    【讨论】:

    • 我刚回到这个答案,又发现自己很困惑。你能再解释一下你是如何得到 f(n) 的公式的吗?
    • @John 更新了帖子以澄清符号并修复一些错误。
    猜你喜欢
    • 1970-01-01
    • 2018-10-02
    • 2020-05-03
    • 1970-01-01
    • 2020-12-03
    • 2017-09-11
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    相关资源
    最近更新 更多