C#数据结构与算法系列(十七):时间复杂度(下)

1.常见的时间复杂度

常数阶:O(1)

对数阶:O(log2n)

线性阶:O(n)

线性对数阶:O(nlog2n)

平方阶:O(n^2)

立方阶:O(n^3)

k次方阶:O(2^n)

常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)< Ο(nk) <Ο(2n) ,随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低

从图中可见,我们应该尽可能避免使用指数阶的算法

1.常数阶:O(1)

无论代码执行多少行,只要是没有循环结构等复杂结构,那这个代码的时间复杂度都是O(1)

            int i = 1;

            int j = 1;

            i++;

            ++j;

            int m = i + j;

 上述代码在执行的时候,它消耗的时候并不随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用O(1)来表示它的时间复杂度。

2.对数阶:O(log2n)

            int i = 0;

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

说明:

在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。假设循环x次之后,i 就大于 2 了,

此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2n也就是说当循环 log2n 次以后,这个代码就结束了。

因此这个代码的时间复杂度为:O(log2n)  。 O(log2n) 的这个2 时间上是根据代码变化的,i = i * 3 ,则是 O(log3n) .

 3.线性阶:O(n)

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

                j++;
            }

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

 4.线性对数阶:O(nlogN)

            int i = 1;

            for (int m = 0; m < n; m++)
            {
                while (i<n)
                {
                    i = i * 2;
                }
            }

说明:线性对数阶O(nlogN) 其实非常容易理解,将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是了O(nlogN)

5.平方阶:O(n²)

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

                    k++;

                }
            }

说明:平方阶O(n²) 就更容易理解了,如果把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²),这段代码其实就是嵌套了2层n循环,

它的时间复杂度就是 O(n*n),即  O(n²) 如果将其中一层循环的n改成m,那它的时间复杂度就变成了 O(m*n)

2.平均时间复杂度和最坏时间复杂度

1)    平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,该算法的运行时间。

2)    最坏情况下的时间复杂度称最坏时间复杂度。一般讨论的时间复杂度均是最坏情况下的时间复杂度。 这样做的原因是:最坏情况下的时间复杂度是算法在任何输入实例上运行时间的界限,这就保证了算法的运行时间不会比最坏情况更长。

3)    平均时间复杂度和最坏时间复杂度是否一致,和算法有关(如图:)。

3.空间复杂度

1)     类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)定义为该算法所耗费的存储空间,它也是问题规模n的函数。

2)     空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如快速排序和归并排序算法就属于这种情况

3)     在做算法分析时,主要讨论的是时间复杂度。从用户使用体验上看,更看重的程序执行的速度。一些缓存产品(redis, memcache)和算法(基数排序)本质就是用空间换时间.

猜你喜欢

转载自www.cnblogs.com/vic-tory/p/13191983.html