当前位置 博文首页 > 孔维舸的博客:一文读懂时间复杂度——大O表示法

    孔维舸的博客:一文读懂时间复杂度——大O表示法

    作者:[db:作者] 时间:2021-06-13 12:13

    算法时间复杂度定义

    在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况并确定T(n)的数量级。算法的时间复杂度,也就是算法的时间量度,记做:T(n) = O(f(n))。它表示随时间问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数

    这样用大写O()来体现时间复杂度记法,我们成为大O表示法。
    推导大O表示法的公式
    1、用常数1取代运行时间中的所有加法常数。
    2、在修改后的运行次数函数中,只保留最高阶项。
    3、如果最高阶项存在且不是1,则去除与这个项相乘的函数。

    常数阶

    //从1加到100
    int sum = 0,n = 100;//执行一次
    sum = (1 + n)*n/2;	//执行一次
    printf("%d",sum);	//执行一次
    

    这个算法的运行次数我们用大O表示法来表示的话就是O(1)而并非是O(3) 其中没有最高阶所以就如上面的公式所推 用常数1取代运行时间中的所有加法常数。

    线性阶

    废话不多说我们直接上代码

    int i;
    for(i = 0; i < n; i++)	//执行了n次
    {
    	printf("%d",i);
    }
    

    因为其中的最高项为n所以用大O表示法来表示就是O(n)

    对数阶

    int i;
    while(count < n)
    {
    	count = count * 2;
    }
    

    由于每次count乘以2之后,就距离n更近一分。也就是说有多少个2相乘后大于n,则会退出循环。由 2^x=n 得到 x=log2n所以这个时间复杂度就表示为O(logn)。

    平方阶

    int i,j;
    for(i = 0;i < n; i++)
    {
    	for(j = 0;j < n;j++)
    	{
    	}
    }
    

    对于外层的循环,不过是内部这个时间复杂度为O(n)的语句,在循环n次,所以时间复杂度为O(n^2)。

    之后我们再来看下接下来的这段代码

    int i,j;
    for(i = 0;i < n; i++)
    {
    	for(j = i;j < n; j++)	//注意这里是 j = i
    	{
    	}
    }
    

    由于当i = 0时,内循环执行了n次,当i = 1时,执行了n-1次,…当i=n-1时,执行了1次。所以总执行次数为:在这里插入图片描述
    如大O表示法所推导,
    1、没有加法常数不予考虑
    2、只保留最高阶项,因此保留n^2/2
    3、去除这个项相乘的常数,也就是去除1/2,
    最终这段代码的时间复杂度为O(n^2)

    常见的数量级大小:O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

    大家可以看到其实时间复杂度并不难唯一的难点是一些对数列公式的推导。

    参考:
    《大话数据结构》