算法复杂度分为时间复杂度空间复杂度二者也是衡量代码的好坏两个重要指标:

  • 时间复杂度:指执行算法所需要的计算工作量;
  • 间复杂度:指执行这个算法所需要的内存空间。

算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度。

1. 概念理解

1.1 基本执行次数:T(n)

由于运行环境和输入规模的影响,代码的绝对执行时间是无法估计的,但我们可以估算出代码的基本执行次数。

一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用这个函数来表达相对时间,可以记作 T(n)。

1.2 时间复杂度:O(n)

因为执行规则具有不确定性(文章下面就列举4种可能), 所以T(n) 不足以分析和比较一段代码的运行时间,就有了渐进时间复杂度(asymptotic time complexity)的概念,官方的定义如下:

若存在函数 f(n),使得当n趋近于无穷大时,T(n)/ f(n)的极限值为不等于零的常数,则称 f(n)是T(n)的同数量级函数。记作 T(n)= O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称:时间复杂度。

渐进时间复杂度用大写“O”来表示,所以也被称为大O表示法。

算法时间复杂度里有O(1), O(n), O(logn), O(nlogn), O(n^2)的概念,这是算法的时空复杂度的表示。

它不仅仅用于表示时间复杂度,也用于表示空间复杂度

O后面的括号中有一个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量

1.3 空间复杂度:S(n)

与时间复杂度类似,空间复杂度是指算法在计算机内执行时所需存储空间的度量,记作:S(n)=O(f(n)) 。

上面提到过,O(n)不仅仅用于表示时间复杂度,也用于表示空间复杂度。

2. 场景分析:

这是针对时间复杂度的场景分析,时间复杂度排序为:O(1)< O(log2n)< O(n)< O(n^2)

场景1:T(n) =  O(1)

表示算法的运行时间为常量,这是最低的时空复杂度了,也就是耗时/耗空间与输入数据大小无关,无论输入数据增大多少倍,耗时/耗空间都不变。

哈希算法就是典型的O(1)时间复杂度,无论数据规模多大,都可以在一次计算后找到目标(不考虑冲突的话)。

场景2:T(n) =  O(log2n)

当数据增大n倍时,耗时增大log n倍(这里的log是以2为底的,比如,当数据增大256倍时,耗时只增大8倍,是比线性还要低的时间复杂度)。

二分查找就是O(log n)的算法,每找一次排除一半的可能,256个数据中查找只要找8次就可以找到目标。

场景3:T(n) =  O(n)

表示该算法是线性算法,数据量增大几倍,耗时也增大几倍。

比如常见的for循环遍历,要找到一个数组里面最大的一个数,你要把n个变量都扫描一遍,操作次数为n,那么算法复杂度是O(n)。

场景4:T(n) =  O(n^2)

代表数据量增大n倍时,耗时增大n的平方倍,这是比线性更高的时间复杂度。

比如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。

在编程的世界中有着各种各样的算法,除了上述的四个场景,还有许多不同形式的时间复杂度,我们按照时间复杂度,按数量级递增依次排列为:

常数阶 O(1) <  对数阶(log2n) < 线性阶 O(n)<  线性对数阶 O(nlog2n) < 平方阶 O(n^2) < 立方阶 O(n^3) < k次方阶 O(n^k) < 指数阶 O(2^n)……

3. 算法比较:

排序算法

  平均时间

最差情形

稳定度

额外空间

备注

冒泡

 O(n 2 )

 O(n 2 )

稳定

O(1)

n 小时较好

交换

  O(n 2 )

  O(n 2 )

不稳定

O(1)

n 小时较好

选择

 O(n 2 )

 O(n 2 )

不稳定

O(1)

n 小时较好

插入

 O(n 2 )

 O(n 2 )

稳定

O(1)

大部分已排序时较好

基数

O(log R B)

O(log R B)

稳定

O(n)

B 是真数 (0-9) ,

R 是基数 ( 个十百 )

Shell

O(nlogn)

O(n s ) 1<s<2

不稳定

O(1)

s 是所选分组

快速

O(nlogn)

O(n 2 )

不稳定

O(nlogn)

n 大时较好

归并

O(nlogn)

O(nlogn)

稳定

O(1)

n 大时较好

O(nlogn)

O(nlogn)

不稳定

O(1)

n 大时较好

 

借鉴了一些官方统计,再加上自己的理解,整理了一篇比较全面的关于介绍时间复杂度的博客,内容涵盖了从概念延伸到原理,再到算法的总结,希望对大家有一定的帮助。

 

少侠请留步 ... ヾ(◍°∇°◍)ノ゙ ... 
欢迎点赞、评论、加关注,让更多人看到学到赚到
更多精彩,请关注我的"今日头条号":Java云笔记

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐