我无法弄清楚这个功能的时间和空间复杂性。
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(n 3 )的范围内。但是,当函数继续运行时,第二个循环的长度会发生变化。在第一次迭代时,向量中只有一个元素是空向量。在第二次迭代中,它包含长度为1的n
个向量,其中n
是第一个字符串向量的长度。所以我真的不确定这会对事情产生什么影响。
至于空间复杂性,由于用于存储结果的2D矢量,我认为它位于 O(m * n)附近。我不确定m
和n
到底在哪里。
答案 0 :(得分:1)
计算长度为stringCombinations()
的{{1}}向量的笛卡尔积的n
函数的复杂度为 O(n * k ^ n)。< / p>
让k
成为函数v
的参数,让 n 表示stringCombinations()
。让 v1 ... vn 表示v.size()
的元素,让| u |表示向量 u 中的元素数。
该函数计算 n 向量 v1 ... vn 的笛卡尔积。结果向量v
的大小为| v1 | * | v2 | * .... * | vn |。 results
的每个元素都是大小为 n 的向量。设 k 表示max(| v1 |,...,| vn |)。
现在我们可以估计算法的复杂性。设 f(i)表示第一循环的 i 次迭代中第二循环的迭代次数。然后我们将得到O( n * f(n) * k ),因为 k 是上层限制了第三个循环的迭代次数。
对于 f(n),我们有以下公式。如果 ki 是 vi 中的字符串数,那么 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 表示的第一个元素results
的大小。在使用values
的第二次迭代中,每个元素vec = {s1,s2,...}
将替换为 k2 元素。 r={s}
,{s,s1}
,...因此,第二次迭代后{s,s2}
向量的大小将等于 k1 * k2 。在每次后续迭代 i 之后,result
的大小将乘以 ki 。此大小将确定第一个循环的下一次迭代中第二个循环的迭代次数。所以* f(i + 1)= 1 * k1 * ... * ki 。
一个例子很方便。让result
。这里 n = 2.在第一次迭代开始时我们有
values = {{"1","2"},{"3","4","5"}}
在第二次迭代开始时我们有
results = {{}}, vec={"1","2"}, *k1* = 2, *f(1)*=1
最后我们有
results = {{"1"},{"2"}}, vec={"3","4","5"}, *k2*=3, *f(2)*=2
操作次数为 T = f(1) * k1 + f(2) * k2 。当 k = max( k1 , k2 )= 3时,我们有 T &lt; = 3 *(< em> f(1) + f(2))&lt; = 3 * f(2) * 2。 更新结束
另请注意, results = {{"1","3"},{"1","4"},{"1","5"},
{"2","3"},{"2","4"},{"2","5"}}
中的元素数量受O( n * k ^ n )的限制,因此这也是第二个循环。
正如您所说,如果我们让 m = k ^ n ,那么复杂性就是O( m * n )。然而,这种表示法可能会产生误导,因为输入数组可以被 k 数组视为 n ,因此最好根据输入的维数进行复杂性估计。数组,所以它是O( n * k ^ n )。