算法的时间复杂度
来源:互联网 发布:java正则判断是否数字 编辑:程序博客网 时间:2024/05/02 01:45
在计算算法复杂度时一般只用到大O符号,Landau符号体系中的小o符号、Θ符号等等比较不常用。这f (n) = Ο(g (n)) 表示存在一个常数C,使得在当n趋于正无穷时总有 f (n) ≤ C * g(n)。
例如,O(2n^2+n +1) = O (3n^2+n+3) = O (7n^2 + n) = O ( n^2 ) ,一般都只用O(n^2)表示就可以了。注意到大O符号里隐藏着一个常数C,所以g(n)里一般不加系数。如果把f(n)当做一棵树,那么O(g(n))所表达的就是树干,只关心其中的主干,其他的细枝末节全都抛弃不管。
O(1), O(log n), O(n), O(n * log n) ,O(n^k), O(a^n), O(n!)越往后,复杂度越大。
复杂度举例:
(1) O(1) 常数级复杂度,也就是说程序运行的时间与需要处理的数据大小无关。通常把比较大小、加减乘除等简单的运算都当做常数级复杂度。
(2) O(logn) 将一个10进制整数转化为2进制整数。lnn,lgn对数O(logn)常底数是无所谓的的,因为有换底公式 ,因为a,b都是常数,所以对于对数一般不需要注明底数,所以不用纠结底数到底是2还是10啦,因为无所谓啦……常数次幂也是无所谓的啦,因为有
(3) O(n):判断一个元素是否属于一个大小为n的集合/列表;找出n个数中的最大值;
(4)O(n * log n) 快速排序法
(5) O(n^2) 最直白的两两比较然后排序方法,需要n*(n-1)/2次比较,所以是O(n^2)级。
(6) O(2^n) 列出所有长度为n的0,1字符串之类的穷举计算
(7)O(n!) 列出n个元素的全排列之类的穷举计算
复杂度与时间效率的关系:
c < logn < n < n*logn < n2 < n3 < 2n < 3n < n! (c是一个常量)
|--------------------------|--------------------------|-------------|
较好 一般 较差
其中c是一个常量,如果一个算法的复杂度为c 、 logn 、n 、 n*logn,那么这个算法时间效率比较高,如果是 2n , 3n ,n!,那么稍微大一些的n就会令这个算法不能动了,居于中间的几个则差强人意。
一个算法,对于一个规模是n的输入,需要T(n)的时间进行运算。T(n)的具体值,一方面取决于算法,另一方面和计算用的工具也有关。但我们关心的是,当n扩大100倍以后,T(n)是几乎不变,还是扩大了100倍、10000倍或者怎样。我们关心的是规模扩大后,运算时间增长得有多快,是一个相对的结果,而不是绝对结果。
建立一个空列表,需要的时间总是固定的,就是O(1);如果有一句for或者while的语句,把同一行代码运算了n次,那么就是O(n)级的复杂度;如果for下面还有for,各自要算n次,那么就是n^2的复杂度,以此类推。
常用计算:
算数级数:T(n)=1+2+3+4…+n=n(n+1)/2=O(n2),算数级数的是和末项平方同阶;
幂方级数:T2(n)=12+22+32+…+n2=O(n3),T3(n)=O(n4),阶数是(幂方+1)的级数;
几何级数:Ta(n)=a0+a1+a2+…+an=O(an),与末项同阶;
收敛级数:
1+1/2^2+1/3^2+1/4^2+…=O(1)
例如:
(1)T(n)=T(n-1)+O(n)时间复杂度是O(n^2)
T(n-1) = T(n-2) + O(n-1)…
所以T(n) =O(n) + O(n-1) + O(n-2) +…+ O(1) + T(0)
这个T(0)一般为某个常数,前面的加起来是O(n(n+1)/2),也就是O(n^2)。
(2)T(n)=T(n/2)+O(1)= O()=O(logn)分治算法,底数是无所谓的。
利用实例来分析不同算法的不同时间复杂度对程序的影响:
斐波那契数列:
一开始有一对小兔子。小兔子需要一个月以后才能长成大兔子从而拥有生育能力;所有拥有生育能力的大兔子每个月都会生一对小兔子。所有的兔子都长生不老,问第n个月一共有多少兔子呢?
观察规律得到:
月份
1
2
3
4
5
6
7
兔/只
1
1
2
3
5
8
13
规律是F(n)=F(n-1)+F(n-2);
(1)很容易想到的算法,指数级复杂度;O(2^n),效率太低了
intF[1]=1,F[2]=1;
if(n<3)
sum=1;
else
sum=F[n-1]+F[n-2];
return sum;
(2)for语句,循环n-2次,O(n)级的复杂度,相比第一次的算法这次要简单得多(每一步都有保存数据,消耗空间复杂度以获得较好的时间复杂度。)
int x=1;y=1;
for(int i=2;i<n;i++)
{
temp=x;
x=y;
y=x+temp;
}
(3) 矩阵乘方,复杂度是O(log n),速度很快
由此,我们求一个矩阵的n次方即可。两个2维矩阵的乘法次数可以看作常量。矩阵n次方利用分治法,只需要O(logn)的复杂度就能计算出来.算法代码如下:
staticintFibonacci3(intn)
{
int[,]a=newint[2,2]{{1,1},{1,0}};
int[,]b=MatirxClub(a,n);
returnb[1,0];
}
staticint[,]MatirxClub(int[,]a,intn)
{
if(n==1){returna;}
elseif(n==2){returnMatirx(a,a);}
elseif(n%2==0)
{
int[,]temp=MatirxClub(a,n/2);
returnMatirx(temp,temp);
}
else
{
int[,]temp=MatirxClub(a,n/2);
returnMatirx(Matirx(temp,temp),a);
}
}
staticint[,]Matirx(int[,]a,int[,]b)
{
int[,]c=newint[2,2];
for(inti=0;i<2;i++)
{
for(intj=0;j<2;j++)
{
for(intk=0;k<2;k++)
{
c[i,j]+=a[i,k]*b[k,j];
}
}
}
returnc;
}
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- 算法的时间复杂度
- isNotEmpty与isNotBlank的区别
- Quartz将Job保存在数据库中所需表的说明
- live555学习笔记1-引子
- Ios中,在UIImage中写文字的一点心得。
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- 算法的时间复杂度
- getsockname与getpeername用法与区别
- odbc快速打开命令
- Qt笔记-2-简单布局
- spring整合quartz并持久化
- UIKeyboard键盘
- HDU1573 X问题 解同余方程组
- asp.net mvc 路由功能
- JVM调优总结 -Xms -Xmx -Xmn -Xss