算法复杂度
算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度。)
时间复杂度
为了计算时间复杂度,我们一般会估算算法的操作数,而我们用最坏情况下的复杂度表示,为T(n),指的是最大的运行时间。
我们有一种通用的方法:大O表示法,T(n) = O(f(n))。称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
f(n)是辅助函数,可以看成是代码每个执行次数的和。O(f(n))就是n趋于无限大的时候,f(n)得到极限值。O(f(n))可以用来表示时间复杂度。
常见的时间复杂度量级有:
- 常数阶O(1)
- 对数阶O(logN)
- 线性阶O(n)
- 线性对数阶O(nlogN)
- 平方阶O(n^2)
- 立方阶O(n^3)
- k次方阶O(n^k)
- 指数阶O(2^n)
- 阶乘阶O(n!)
时间复杂度按消耗的时间:O(1) < O(logn) < O(n) < O(nlogN) < O(n^2) < O(n^3) < O(n^k) < O(2^n) <O(n!)
常数阶O(1)
public static void mian(String[] args)
{
System.out.print("Hello,world!");
System.out.print("你好!");
System.out.print("世界!");
}
这就是常数阶,上面例子,有三行代码被执行,实际上T(n)=O©,c为常数,例子中的3等,但常数用标准记法O©=O(1)。常数被看成1在大O表示法中。
对数阶O(logn)
public static void mian(String[] args)
{
int i=1;
while(i<n)
{
i=i*2;
}
}
例子中可以看到,在while循环中,i每次都乘以2,每乘一次就越接近n,当x次后,用数学式子表示,n=2*x,则x=log2n,则此时x=log2n是循环的最大次数,此时时间复杂度为O(logn)。
线性阶O(n)
public static void mian(String[] args)
{
int x=0;
for(int i=0;i<n;i++)
{
x++;
}
}
例子中,x++共执行了n次,最终x=n,因此时间复杂度为O(n)。
线性对数阶O(nlogn)
public static void mian(String[] args)
{
for(int i=0;i<n;i++)
{
int j=1;
while(j<n)
{
j=j*2;
}
}
}
例子中就是将对数阶循环了n次,n*O(logn),时间复杂度就是O(nlogn)。
平方阶O(n^2)
public static void mian(String[] args)
{
int x=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
x++;
}
}
}
例子中,就是嵌套循环,n乘n次的循环,x最终就是x=n^2 ,时间复杂度为O(n^2 )。如果j<m,则时间复杂度为O(n*m)。在大体上表示就是O(n^2 )。
立方阶O(n^3 ) 和k次方阶O(n^k)
这两个就是和平方阶类似,如果循环嵌套了三次就是立方阶,时间复杂度就是O(n^3 ),如果循环嵌套了k次,就是k次方阶,时间复杂度就是O(n^k)。
指数阶O(2^n)
public static void mian(String[] args)
{
}
阶乘阶O(n!)
public static void mian(String[] args)
{
}
空间复杂度
S(n)=O(f(n)),一个算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括这三个方面:
- 存储算法本身所占用的存储空间
- 算法的输入输出数据所占用的存储空间
- 算法在运行过程中临时占用的存储空间
第一,要减少算法本身占用的存储空间,我们就要尽可能的写简短的代码。
算法的输入输出数据占用的空间由要解决的问题影响,所以算法的不同不怎么影响这部分的空间占用。
对算法的空间复杂度影响最大的是算法运行过程中临时占用的存储空间。不同的算法写出来,运行时申请的临时空间会有较大的不同。
public static void mian(String[] args)
{
int n=10;
int []nums=new int[n];
}
这时的n是定死的为十,当没有初始值时,由人输入的时候,这个程序运行时申请的临时空间就随n的变化而变化。
所以,如果程序所占用的存储空间和输入值无关,则该程序的空间复杂度就为 O(1);反之,如果有关,则需要进一步判断它们之间的关系:
- 如果随着输入值 n 的增大,程序申请的临时空间成线性增长,则程序的空间复杂度用 O(n) 表示;
- 如果随着输入值 n 的增大,程序申请的临时空间成 n^2 关系增长,则程序的空间复杂度用 O(n^2) 表示;
- 如果随着输入值 n 的增大,程序申请的临时空间成 n^3 关系增长,则程序的空间复杂度用 O(n^3) 表示;
- 如果随着输入值 n 的增大,程序申请的临时空间成 n^k 关系增长,则程序的空间复杂度用 O(n^k) 表示。