1、什么是复杂度:
复杂度分为:时间复杂度(渐进时间复杂度)与空间复杂度(渐进空间复杂度)。
时间复杂度:表示算法的执行时间随数据规模增长的变化趋势。
空间复杂度:表示算法的存储空间与数据规模之间的增长关系。
2、为什么要知道复杂度
①。事后统计法:跑一边代码就能得到运行时间和占用内存大小。
②。测试环境与数据规模会影响测试结果。
③。在不同配置的计算机下测试,得到的测试结果往往不同。
在数据规模不大的情况下,插入排序比快速排序快,如果是一组有序的数据,代码执行的时间很短。
④。所以在这种情况下,我们往往不需要数据规模,可以粗略地估算出算法的执行效率。
3、时间复杂度分析:
int plus(int n)
{
int sum = 0;
int i = 1;
for (; i <= n; ++i)
{
sum = sum + i;
}
return sum;
}
假设处理器运行每段代码的时间相同,设为t,三四两行执行2t,5,7行都执行了n次,所以代码总的执行时间为(2n+2)*t;可以看出来,所有代码的执行时间 T(n) 与每行代码的执行次数成正比。
int plus(int n)
{
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i)
{
j = 1;
for (; j <= n; ++j)
{
sum = sum + i * j;
}
}
}
我们还是假设每段代码执行的时间为t,3,4,5执行1次,6,8执行n次,9,11执行n* n次,所以代码的执行总时间为:(2n*n+2n+3)*t。
用大O表示法表示:T(n) = O(f(n)).
大 O 时间复杂度表示法。大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势。
所以可以想象当n无穷大的时候,常量,低阶和系数并无会影响执行时间的增长趋势,所以,上述两个复杂度可以表示为:O(n);O(n²);
①:我们在分析一个算法、一段代码的时间复杂度的时候,也只关注循环执行次数最多的那一段代码就可以了。
②:总复杂度等于量级最大的那段代码的复杂度
③:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
4、常见的时间复杂度:
从低阶到高阶有:O(1)、O(logn)、O(n)、O(nlogn)、O(n² )。
越高阶复杂度的算法,效率就越低。
O(logn):
i=1;
while (i <= n)
{
i = i * 2;
}
i是取值:2,4,8,16…所以循环次数为O(log2n)。
如果换成i= i*3; 复杂度就变成了O(log3n)。
在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)。
5、空间复杂度:
void print(int n)
{
int i = 0;
int[] a = new int[n];
for (i; i < n; ++i)
{
a[i] = i * i;
}
}
跟上面的分析一样,所以整段代码的空间复杂度就是 O(n)。