01.数据结构资料,时间复杂度空间复杂度(数据结构算法基本)
常用资料
算法复杂度
https://www.bigocheatsheet.com
动态演示站点
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
知识结构
算法5大特征
有穷,确切,输入项,输出项,可行性
时间复杂度:
执行算法所需要的计算工作量
一般来说,计算机算法是问题规模n的函数f(n)
,算法的时间复杂度因此记做T(n)=O(f(n))
问题的规模越大,算法执行的时间的增长率与f(n) 的增长率正相关,称作渐进时间复杂度(Asympotic Time Complexity)
计算方式:
- 1.计算次数公式
1+2+3+.......+n;
<?php
$sum=0;
for($i=1;$i<=$n;$i++){
sum+=$i;
}
?>
计算n次,时间复杂度为O(n)
- 2.用常数1来取代所有时间中所有加法常数 比如O(3) 记做O(1)
<?php
function test($n){
echo $n;
echo $n;
echo $n;
}
?>
O(3) 记做O(1)
- 3.在修改后的运算次数函数中,只保留最高阶项
n^2+n+1 则记做O(n^2) - 4.如果最高阶存在且不是1,则去除与这个项相乘的常数
2n^2+3n+1 记做O(n^2)
常数阶:O(1)
线性阶:O(n)
平(立)方阶:O(n^2),O(n^3)
<?php
$sum=0;
for($i=1;$i<=$n;$i++){
for($j=1;$j<=$n;$j++){
$sum+=$j;
}
}
?>
两层循环 O(n^2) 三层O(n^3)
特殊平方阶:O(n^2/2+n/2)-> O(n^2)
for(){
for(){
}
}
for(){
}
echo $a+$b;
n^2+n+1->O(n^2)
对数阶
$i=1;$n=100;
while($i<$n){
$i=$i*2;
}
2^x=n
x=\log_2^n
\log_2^n=\log_2^{10}\log{n}
3^x=n
x=\log_3^n
\log_3^n=\log_3^{10}*\log{n}
最坏情况:最坏情况下的运行时间,一种保证,如果没特殊说明,说的时间复杂度即为最坏情况下的时间复杂度
平均情况:期望的运行时间
空间复杂度:算法需要消耗的内存空间,记作S(n)=O(f(n))
- 包括程序代码所占用的空间
- 输入数据所占用的空间和
- 辅助变量所占用的空间
这3个方面
计算和表示方法与时间复杂度类似,一般用复杂度的渐进性表示
时间复杂度分析
1. 只关注循环执行次数最多的一段代码
大 O 这种复杂度表示方法只是表示一种变化趋势。
我们通常会忽略掉公式中的常量、低阶、系数,只需要记录一个最大阶的量级就可以了。所以我们在分析一个算法、一段代码的时间复杂度的时候,也只关注循环执行次数最多的那一段代码就可以了
C是常数,为何C能省略呢
Cn^2
C(n+1)^2-Cn^2=C(2n+1)
(n+1)^2-n^2=2n+1
2. 加法法则:总复杂度等于量级最大的那段代码的复杂度
3. 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
空间复杂度分析
时间复杂度的全称是渐进时间复杂度,表示算法的执行时间与数据规模之间的增长关系。类比一下,空间复杂度全称就是渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。
void print(int n) {
int i = 0;
int[] a = new int[n];
for (i; i <n; ++i) {
a[i] = i * i;
}
for (i = n-1; i >= 0; --i) {
print out a[i]
}
}
跟时间复杂度分析一样,第 2 行代码中,我们申请了一个空间存储变量 i,但是它是常量阶的,跟数据规模 n 没有关系,所以我们可以忽略。第 3 行申请了一个大小为 n 的 int 类型数组,除此之外,剩下的代码都没有占用更多的空间,所以整段代码的空间复杂度就是 O(n)。