big o是算法分析的常用手段,简单的说就是估计算法的执行时间,我们假设每行代码的时间是一样的,所以就可以理解为代码的执行次数.用n表示数据规模,f(n)表示执行次数,那么执行时间T(n) = O(f(n))表示Tn和执行次数fn成正比
1.看个简单的例子,1+ 1 + n + n ,即时间复杂度 (2n+2)*unit_time
int cal(int n) {
int sum = 0;//执行1次
int i = 1;//执行1次
for (; i <= n; ++i) {//执行n次
sum = sum + i;//执行n次
}
return sum;
}
2.再看一个例子,T(n) = O(2n2+2n+3),即O表示随着n变化时间的趋势的法则,对于函数的概念,可以理解为映射,这里大O表示次数和时间的映射
int cal(int n) {
int sum = 0;//1
int i = 1;//1
int j = 1;//1
for (; i <= n; ++i) {//n
j = 1;//n
for (; j <= n; ++j) {//n*n
sum = sum + i * j;//n*n
}
}
}
3.总结+ 计算手段(下面列的都是): * 大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度
- 计算手段1:只关注循环执行次数最多的一段代码---我们通常会忽略掉公式中的常量、低阶、系数,只需要记录一个最大阶的量级就可以了
- 计算手段2:加法法则,如果两段代码是满足加法法则(即没有嵌套),就是次数是相加的,那么最终取最大的----如果 T1(n)=O(f(n)),T2(n)=O(g(n));那么 T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n))).
- 如下满足加法法则,即n方
int cal(int n) {
int sum_1 = 0;//sum_1 是100次
int p = 1;
for (; p < 100; ++p) {
sum_1 = sum_1 + p;
}
int sum_2 = 0;//sum_2是n次
int q = 1;
for (; q < n; ++q) {
sum_2 = sum_2 + q;
}
int sum_3 = 0;//sum_3是n的平方
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1;
for (; j <= n; ++j) {
sum_3 = sum_3 + i * j;
}
}
return sum_1 + sum_2 + sum_3;
}
int cal(int n) {
int ret = 0;
int i = 1;
for (; i < n; ++i) {
ret = ret + f(i);//n次
}
}
int f(int n) {
int sum = 0;
int i = 1;
for (; i < n; ++i) {
sum = sum + i;//n 次
}
return sum;
}
4.常见的算法复杂度,复杂度分为两类:多项式量级和非多项式量级.非多项式量级只有两个:O(2^n) 和 O(n!),我们把时间复杂度为非多项式量级的算法问题叫做NP问题
- O(1) 常数级别的都归为O(1),比如下面的代码执行了3次,也是O(1),一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。
int i = 8;
int j = 6;
int sum = i + j;
i=1;
while (i <= n) {
i = i * 2;
}
- 线性阶O(N) O(M+N)
- 线性对数阶 O(NlogN)
- 平方阶 O(n^2) ,O(n^3) ...O(n^k)
5.对于空间复杂度,用的最多的是O(1),O(n),O(n^2)。相对简单,不做深入