算法复杂度分析

发布时间 2023-12-12 13:55:39作者: 陆留生信奥艺术

常见的时间复杂度量级有:常数阶O(1),对数阶O(logn),线性阶O(n),线性对数阶O(nlogn),平方阶O(n2),立方阶O(n3),K次方阶O(nk),指数阶O(2n)。他们的时间复杂度越来越大,执行的效率越来越低。

下面选取一些较为常用的来讲解一下。

常数阶O(1)

for(int i = 1; i <= 100; i++)
    sum += i;

代码执行次数是一个常数,不随n的变化而变化,那这个代码的时间复杂度就都是O(1),如下的代码中虽然含有for循环,但循环次数是100次,不随问题规模变化而变化,因此是常数级O(1)的时间复杂度:

线性阶O(n)

for(int i = 1; i <= n; i++)
    sum += i;

这段代码,for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度。

对数阶O(logn)

同样是for循环,但这段代码的时间复杂度是O(logn),因此不能单纯认为for循环就一定是O(n)的。

for(int i = 1; i <= n; i *= 2)
    cnt++;

在这个for循环里,i 开始是1,然后不是自增1,而是自乘2,因此i的值依次是1248......2x ,也就是当2的x次方大于n时,跳出循环,因此x =ogn, 程序执行了logn次,时间复杂度为:O(logn)

线性对数阶O(nlogn)

线性对数阶O(nlogn) 其实非常容易理解,将时间复杂度为O(logn) 的代码循环n遍的话,那么它的时间复杂度就是 n×O(logn)。

就拿上面的代码加一点修改来举例:

for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j *= 2)
        cnt++;

平方阶O(n2)

平方阶O(n2)就更容易理解了,如果把O(n)的代码再嵌套循环一遍,它的时间复杂度就是O(n2) 了。

for(int i = 1; i <= n; i++)
   for(int j = 1; j <= n; j++)
        cnt++;

其实冒泡排序的时间复杂度也是O(n^2^),以下代码中,当i=1时,执行n-1次,i=2时,执行n-2次......因此总的执行次数也就是 (n-1)+(n-2)...+2+1就是n*(n-1)/2,显然n2的量级更大,因此常数项和n/2可以忽略,时间复杂度即为O(n2):

for(int i =1; i<=n; i++)
   for(int j=1; j<=n-i; j++)
        if(a[j] > a[j+1])
            swap(a[j], a[j+1]);

阶乘 O(n!)

比如用枚举的方法求1~n的全排列,时间复杂度是 O(n!),效率很低。 全排列