我是搬运工,写下来仅作为自己复习哈。
我们来看一下这个例子,用的是java,内容就是打印8条语句,问这个程序的时间复杂度是多少?
public class TS {
public static void main(String[] args) {
System.out.println("111");
System.out.println("111");
System.out.println("111");
System.out.println("111");
System.out.println("111");
System.out.println("111");
System.out.println("111");
System.out.println("111");
}
}
O(8)? 当然不是!!!按照时间复杂度的概念“T(n)是关于问题规模为n的函数”,这里跟问题规模有关系吗?没有关系,用我们的第一个方法,时间复杂度为O(1)。
第二个例子:(线性阶)
public class TS {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=100;i++) {
sum = sum + i;
}
}
}
时间复杂度为O(n)。
第三个例子:(平方阶)
public class TS {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=100;i++) {
for(int j=1;j<=100;j++)
sum = sum + i;
}
}
}
外层i的循环执行一次,内层j的循环就要执行100次,所以外层执行100次,那么总的就需要执行100*100次,那么n次呢?就是n的平方次了。所以时间复杂度为:O(n^2)。
平方阶的另外一个例子:
public class TS {
public static void main(String[] args) {
int sum = 0;
for(int i=1;i<=100;i++) {
for(int j=i;j<=100;j++)
sum = sum + i;
}
}
}
当i=1的时候执行n次,当n=2的时候执行(n-1)次,…
一直这样子下去就可以构造出一个等差数列:n+(n-1)+(n-2)+…+2+1
根据等差数列的求和公式:或者
求和易得:n+n*(n-1)/2整理一下就是n*(n+1)/2然后我们将其展开可以得到n^2/2+n/2。
根据我们的步骤走,保留最高次项,去掉相乘的常数就可以得到时间复杂度为:O(n^2)
第四个例子:(对数阶)
public class TS {
public static void main(String[] args) {
int i=1;
int n= 100;
while(i<n) {
i = i*2;
}
}
2^x = n,所以时间复杂度为O(log2n)。
时间复杂度所耗费的时间从小到大依次是:
O(1 )< O(logn) < O(n) < O(n*logn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)
最坏情况与平均情况:
平均运行时间是期望的运行时间。
最坏的运行时间是一种保证。我们提到的运行时间都是最坏的运行时间。
可以通过空间来换取时间。
原文:https://blog.csdn.net/szlg510027010/article/details/82426240
三. 再次进阶
求该方法的时间复杂度
long aFunc(int n) {
if (n <= 1) {
return 1;
} else {
return aFunc(n - 1) + aFunc(n - 2);
}
}
参考答案:
显然运行次数,T(0) = T(1) = 1,同时 T(n) = T(n - 1) + T(n - 2) + 1,这里的 1 是其中的加法算一次执行。
显然 T(n) = T(n - 1) + T(n - 2) 是一个斐波那契数列,通过归纳证明法可以证明,当 n >= 1 时 T(n) < (5/3)^n,同时当 n > 4 时 T(n) >= (3/2)^n。
所以该方法的时间复杂度可以表示为 O((5/3)n),简化后为 O(2 n)。
可见这个方法所需的运行时间是以指数的速度增长的。如果大家感兴趣,可以试下分别用 1,10,100 的输入大小来测试下算法的运行时间,相信大家会感受到时间复杂度的无穷魅力。