我们假设计算机运行一行基础代码需要执行一次运算,
int aFunc(int n){
for(int i=0;i<n;i++{
printf("hello world\n");}
return 0;//需要执行一次
}
这个方法总共需要执行n+1+n+1=2n+2次运算,for循环执行了n+1次
我们把算法需要执行的运算次数用含有n的函数表示,即T(n)。此时为了估算算法运行的时间,和简化算法分析,我们引入了时间复杂度的概念。
定义:存在常数c和函数f(N),使得当N>c时T(N)<=f(N),表示为T(n)=O(f(n))
例如当N>=2的时候,f(n)=n^2总是大于T(n)=n+2的,于是我们说f(n)的增长速度是大于或者等于T(n)的,也就是说f(n)是T(n)的上界,可以表示为T(n)=O(f(n))。
算法的时间复杂度,用来度量算法的运行时间,记作:T(n)=O(f(n))。它表示随着输入大小n的增大,算法执行需要的时间的增长速度可以用f(n)来描述。
显然如果T(n)=n^2,那么T(n)=O(n^2),T(n)=O(n^3),Tn=O(n^4)都是成立的,但是因为第一个f(n)的增长速度与T(n)是最接近的,所以我们说这个算法的时间复杂度为O(n^2)。
常数项对函数的增长速度影响并不大,所以当T(n)=c时,c为一个常数时,我们说这个算法的时间复杂度为O(1),如果不等于常数项时,直接将常数项省略。
例如 T(n)=2,那么时间复杂度为O(1)
T(n)=n+29,那么时间复杂度为O(n)
我们知道高次项对函数的增长速度的影响是最大的。n^3的增长速度远超n^2的,同时n^2的增长速度是远超n的。因此因为要求的精度不高,我们忽略低次的。
比如:T(n)=n^3+n^2+29此时时间复杂度为O(n^3)
因为函数的阶数对函数的影响是最显著的,因此我们忽略与最高阶相乘的常数
T(n)=3n^3,此时的时间复杂度为O(n^3)
时间复杂度的计算还可以用数学来计算
例如
void aFunc(int n) {
for(int i = 0; i < n; i++) { // 循环次数为 n
printf("Hello, World!\n"); // 循环体时间复杂度为 O(1)
}
}
此时的时间复杂度为O(n*1)=O(n)
void aFunc(int n) {
for(int i = 0; i < n; i++) { // 循环次数为 n
for(int j = 0; j < n; j++) { // 循环次数为 n
printf("Hello, World!\n"); // 循环体时间复杂度为 O(1)
}
}
}
这样的时间复杂度就为O(n*n*1)=O(n^2)
对于顺序执行的语法或者算法,总的时间复杂度等于其中最大的时间复杂度
void aFunc(int n) { // 第一部分时间复杂度为 O(n^2)
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
printf("Hello, World!\n"); }
} // 第二部分时间复杂度为 O(n)
for(int j = 0; j < n; j++) {
printf("Hello, World!\n"); }
}
此时时间复杂度为 max(O(n^2), O(n)),即 O(n^2)。
条件判断语句也和顺序执行的一样,都是看最大的时间复杂度。
时间复杂度分析的基本策略是:从内到外分析,一定要从函数里面进行分析
本文深入探讨了算法的时间复杂度概念,通过实例讲解了如何计算和简化算法的时间复杂度,包括常数时间复杂度O(1)、线性时间复杂度O(n)以及更高阶的时间复杂度如O(n^2)等。

840

被折叠的 条评论
为什么被折叠?



