有人可以仔细解释一下我如何弄清楚这段代码的时间复杂度吗?
int f(int n)
{
int sum = 0;
while (n>1)
{
sum +=g(n)
n = sqrt(n)
}
return sum;
}
其中g(n)由下式给出:
int g(int n)
{
int sum = 0;
for (int i = 1; i<n; i*=2)
sum +=i;
return sum;
}
谢谢!
答案 0 :(得分:1)
一种更具体的证明结果的方法:
如先前的正确回答所述,g(n)
的复杂度为O(log n)
。 g(n)
中的循环执行的准确次数为floor(log2(n)) + 1
。
现在f(n)
。相对于n
的原始值,循环m
的第n
次迭代后的n > 1
的值是:
由此,使用循环条件f(n)
,此循环执行的次数为:
这使人们可以将(*)
的复杂度函数表示为求和:
在O(1)
中,我使用了一个事实,即四舍五入的数字与其原始值仅相差小于 1(因此(**)
)。在(**)
中,我将标准结果用于几何级数和。
n
中带下划线的项的幂为2。当O(log n + log log n) = O(log n)
趋于无穷大时,该项消失,因此带下划线的项本身收敛为2。
由于第一项占主导地位,因此最终的复杂度仅为 void change(int** ptr) {
**ptr = 50;
*ptr = nullptr;
}
void change(int*& ptr) {
*ptr = 50;
ptr = nullptr;
}
int main()
{
int a = 5;
int* ptr = &a;
int** ptr2 = &ptr;
std::cout << "value: " << a << std::endl;
std::cout << "value: " << ptr << std::endl;
std::cout << "value: " << ptr2 << std::endl;
change(ptr2);
//change(ptr);
std::cout << "value: " << a << std::endl;
std::cout << "value: " << ptr << std::endl;
std::cout << "value: " << ptr2 << std::endl;
system("pause");
}
。
答案 1 :(得分:0)
g
的对数是对数的(如果您将其传递给n
,则其循环将重复log[2](n)
次,因为它将i
的倍数加倍为到达n
。
f
是双对数的-在n
重复中,每个操作中log[2](log[2](n))
的指数减半。
我们可以忽略g
是一个单独的函数这一事实-实际上,它是嵌套在另一个循环中的一个循环。如果我们准确分析g
的重复次数如何随着f
的进行而减少,则可以找到一个更好的限制,但是O(log n * log log n)
足够好。 (复杂性理论就像海鲜:虽然“我吃了蓝鳍金枪鱼”可能是正确的答案,但“我吃了鱼”没错。)
编辑:
但是正确的答案是O(log(n))(最终测试答案),我不明白为什么。...
正如我所说的:
如果我们准确分析
g
的重复次数如何随着f
的进行而减少,我们会找到一个更好的限制
但是,老实说,这比代码更容易从结果中完成。假设n
始于65536。这将为g
提供16个迭代。其根为256,这将允许g
运行8次。下一个是16,用于g
的4次迭代。然后2为4,2为1。这看起来像是几何级数:16+8+4+2+1 = 32-1
,其中32
是2 * log[2](65536)
,与O(log n)一致。
或者您可能会注意到,在f
的第一个迭代中,将有g
的许多迭代,与之相比,g
的所有其他调用都不相关(对数地消失)。由于g
的第一次调用是O(log(n))`,因此我们可以在此处截断它并说这就是复杂性。
答案 2 :(得分:-1)
Big O符号,用于描述函数的渐近行为。基本上,它告诉您函数的增长或下降速度
例如,当分析某种算法时,可能会发现完成大小为n的问题所花费的时间(或步数)是由
给出的T(n) = 4 n^2 - 2 n + 2
如果我们忽略常量(这是有意义的,因为它们取决于程序所运行的特定硬件)和增长较慢的术语,我们可以说“ T(n)”以n ^ 2的顺序增长并写: T(n)= O(n ^ 2)
对于形式定义,假设f(x)和g(x)是在实数的某个子集上定义的两个函数。我们写
f(x) = O(g(x))
(或者f(x)= O(g(x)),对于x->无限更精确),并且仅当存在常量N和C使得
|f(x)| <= C|g(x)| for all x>N
从直觉上讲,这意味着f的增长速度不会快于g
如果a是某个实数,我们写
f(x) = O(g(x)) for x->a
当且仅当存在常数d> 0且C满足以下条件
|f(x)| <= C|g(x)| for all x with |x-a| < d
对于您的情况,应该是
O(n) as |f(x)| > C|g(x)|
来自http://web.mit.edu/16.070/www/lecture/big_o.pdf的引用
for r from 0 to xlist: // --> n time
for c from 0 to ylist: // n time
sum+= values[r][c]
n+1
}
Big O表示法在值非常大时给出了一个假设 将运行n次,而内部循环运行n次
假设n-> 100大于总n ^ 2 10000次运行时间