`

算法时间复杂度分析基础

 
阅读更多

摘要
      本文论述了在算法分析领域一个重要问题——时间复杂度分析的基础内容。本文将首先明确时间复杂度的意义,而后以形式化方式论述其在数学上的定义及相关推导。从而帮助大家从本质上认清这个概念。

前言
      通常,对于一个给定的算法,我们要做 两项分析。第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式、数学归纳法等。而在证明算法是正确的基础上,第二部就是分析算法的时间复杂度。算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。因此,作为程序员,掌握基本的算法时间复杂度分析方法是很有必要的。
      但是很多朋友并不能清晰的理解这一概念,究其原因,主要是因为没有从数学层面上理解其本质,而是习惯于从直观理解。下面,我们就一步步走近算法时间复杂度的数学本质。

算法时间复杂度的数学意义
      从数学上定义,给定算法A,如果存在函数F(n),当n=k时,F(k)表示算法A在输入规模为k的情况下的运行时间,则称F(n)为算法A的时间复杂度
      这里我们首先要明确输入规模的概念。关于输入规模,不是很好下定义,非严格的讲,输入规模是指算法A所接受输入的自然独立体的大小。例如,对于排序算法来说,输入规模一般就是待排序元素的个数,而对于求两个同型方阵乘积的算法,输入规模可以看作是单个方阵的维数。为了简单起见,在下面的讨论中,我们总是假设算法的输入规模是用大于零的整数表示的,即n=1,2,3,……,k,……
      我们还知道,对于同一个算法,每次执行的时间不仅取决于输入规模,还取决于输入的特性和具体的硬件环境在某次执行时的状态。所以想要得到一个统一精确的F(n)是不可能的。为了解决这个问题,我们做一下两个说明:
      1.忽略硬件及环境因素,假设每次执行时硬件条件和环境条件是完全一致的。
      2.对于输入特性的差异,我们将从数学上进行精确分析并带入函数解析式。

算法时间复杂度分析示例
      为了便于朋友们理解,我将不会采用教科书上惯用的快速排序、合并排序等经典示例进行分析,而是使用一个十分简单的算法作为示例。我们先来定义问题。
      问题定义:
      输入——此问题输入为一个有序序列,其元素个数为n,n为大于零的整数。序列中的元素为从1到n这n个整数,但其顺序为完全随机。
      输出——元素n所在的位置。(第一个元素位置为1)

      这个问题非常简单,下面直接给出其解决算法之一(伪代码):

      LocationN(A)
      {
            for(int i=1;i<=n;i++)-----------------------t1
            {
                  if(A[i] == n) ----------------------------t2
                        { return i; }------------------------t3
            }
      }

      我们来看看这个算法。其中t1、t2和t3分别表示此行代码执行一次需要的时间。
      首先,输入规模n是影响算法执行时间的因素之一。在n固定的情况下,不同的输入序列也会影响其执行时间。最好情况下,n就排在序列的第一个位置,那么此时的运行时间为“t1+t2+t3”。最坏情况下,n排在序列最后一位,则运行时间为“n*t1+n*t2+t3=(t1+t2)*n+t3”。可以看到,最好情况下运行时间是一个常数,而最坏情况下运行时间是输入规模的线性函数。那么,平均情况如何呢?
      问题定义说输入序列完全随机,即n出现在1...n这n个位置上是等可能的,即概率均为1/n。而平均情况下的执行次数即为执行次数的数学期望,其解为:

      E
      = p(n=1)*1+p(n=2)*2+...+p(n=n)*n
      = (1/n)*(1+2+...+n)
      = (1/n)*((n/2)*(1+n))
      = (n+1)/2

      即在平均情况下for循环要执行(n+1)/2次,则平均运行时间为“(t1+t2)*(n+1)/2+t3”。
      由此我们得出分析结论:
      t1+t2+t3 <= F(n) <= (t1+t2)*n+t3,在平均情况下F(n) = (t1+t2)*(n+1)/2+t3

算法的渐近时间复杂度
      以上分析,我们对算法的时间复杂度F(n)进行了精确分析。但是,很多时候,我们不需要进行如此精确的分析,原因有下:
      1.在较复杂的算法中,进行精确分析是非常复杂的。
      2.实际上,大多数时候我们并不关心F(n)的精确度量,而只是关心其量级。
      基于此,提出渐近时间复杂度的概念。在正式给出渐近时间复杂度之前,要先给出几个数学定义:

      定义一:Θ(g(n))={f(n) | 如果存在正常数c1、c2和正整数n0,使得当n>=n0时,0<c1g(n)<=f(n)<=c2g(n)恒成立}
      定义二:Ο(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=f(n)<=cg(n)恒成立}
      定义三:Ω(g(n))={f(n) | 如果存在正常数c和正整数n0,使得当n>=n0时,0<=cg(n)<=f(n)恒成立}

      可以看到,三个定义其实都定义了一个函数集合,只不过集合中的函数需要满足的条件不同。有了以上定义,就可以定义渐近时间复杂度了。
      不过这里还有个问题:F(n)不是确定的,他是在一个范围内变动的,那么我们关心哪个F(n)呢?一般我们在分析算法时,使用最坏情况下的F(n)来评价算法效率,原因有如下两点:
      1.如果知道了最坏情况,我们就可以保证算法在任何时候都不能比这个情况更坏了。
      2.很多时候,算法运行发生最坏情况的概率还是很大的,如查找问题中待查元素不存在的情况。且在很多时候,平均情况的渐近时间复杂度和最坏情况的渐近时间复杂度是一个量级的。

      于是给出如下定义:设F(n)为算法A在最坏情况下F(n),则如果F(n)属于Θ(g(n)),则说算法A的渐近时间复杂度为g(n),且g(n)为F(n)的渐近确界

      还是以上面的例子为例,则在上面定义中F(n) = (t1+t2)*n+t3。则F(n)的渐近确界为n,其证明如下:

      证明:
      设c1=t1+t2,c2=t1+t2+t3,n0=2
      又因为 t1,t2,t3均大于0
      则,当n>n0时,0<c1n<=F(n)<=c2n 即 0<(t1+t2)*n<=(t1+t2)*n+t3<=(t1+t2+t3)*n恒成立。
      所以 F(n)属于Θ(n)
      所以 n是F(n)的渐近确界
      证毕

      在实际应用中,我们一般都是使用渐近时间复杂度代替实际时间复杂度来进行算法效率分析。一般认为,一个渐近复杂度为n的算法要优于渐近复杂度为n^2的算法。注意,这并不是说渐近复杂度为n的算法在任何情况下都一定更高效,而是说在输入规模足够大后(大于临界条件n0),则前一个算法的最坏情况总是好于后一个算法的最坏情况。事实证明,在实践中这种分析是合理且有效的。
      类似的,还可以给出算法时间复杂度的上确界和下确界 
      设F(n)为算法A在最坏情况下F(n),则如果F(n)属于Ο(g(n)),则说算法A的渐近时间复杂度上限为g(n),且g(n)为F(n)的渐近上确界。
      设F(n)为算法A在最坏情况下F(n),则如果F(n)属于Ω(g(n)),则说算法A的渐近时间复杂度下限为g(n),且g(n)为F(n)的渐近下确界。

      这里一定要注意,由于我们是以F(n)最坏情况分析的,所以,我们可以100%保证在输入规模超过临界条件n0时,算法的运行时间一定不会高于渐近上确界,但是并不能100%保证算法运行时间不会低于渐近下确界,而只能100%保证算法的最坏运行时间不会低于渐近下确界。

总结
      算法时间复杂度分析是一个很重要的问题,任何一个程序员都应该熟练掌握其概念和基本方法,而且要善于从数学层面上探寻其本质,才能准确理解其内涵。在以上分析中,我们只讨论了“紧确界”,其实在实际中渐近确界还分为“紧确界”和“非紧确界”,有兴趣的朋友可以查阅相关资料。

分享到:
评论

相关推荐

    算法时间复杂度分析基础 (论文)

    算法时间复杂度分析基础算法时间复杂度分析基础算法时间复杂度分析基础

    算法复杂度分析基础课件

    包含算法复杂度分析的基本知识,包含时间复杂度和空间复杂度分析的基本思路

    Minimalist-123#Java-Notes#时间复杂度分析 理解1

    前言在java中摸索几年,在看一些文章中,时间复杂度的词频挺高,是时候看下了,而且也是基础,当是回温一下大学的知识,不能全还给老师,哈哈概念时间复杂度:用来定性

    间接交互模式的时间复杂度分析及应用 (2013年)

    为了定量分析间接交互模式的时间复杂度,提出了3种基础间接交互模式的模糊时间Petri网模型及其模糊时间复杂度.整体交互模式的发起者到接收者的可达树搜索算法没计了包含间接交互模式的整体交互模式的搜索算法,同时...

    计算机算法设计与分析_陈玉福_中科院

    这是一份完整的算法开发设计学习文档,对于系统学习算法设计非常有用,也非常全面,可帮助很扎实地掌握算法开发学习所必备的基础知识

    分类超曲面算法复杂度研究

    分类超曲面算法是一种简单的基于覆盖的分类算法.实验证明该算法具有分类...其次,分析了算法的时间复杂度和空间复杂度.最后,给出了无矛盾样本集的概念,并证明当输入样本集是有限无矛盾样本集的条件下,算法一定是收敛的.

    遍历列表集合:数据结构与算法详解.md

    全面阐述了列表这种数据结构的特点,以及使用循环和迭代器遍历列表的两种方式,并分析了算法时间复杂度。最后,列出了遍历算法在数据统计、查找和元素操作等方面的应用实例,内容结构清晰,既具概念性又着眼实用。 适合...

    算法与数据结构基础.zip

    算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、...

    基于C++解决钻石金字塔问题(算法设计与分析)【100011783】

    通过测试也发现这几种算法时间复杂度还是有一定差距,所以优化算法非常有必要。不过测试仍是在相对的基础上,因为每次重复使用算法之前都要先初始化 A 数组或者 sum 数组,也要耗一定时间。而且最后一个算法虽然时间...

    模式匹配算法的效率分析与改进

    模式匹配是一种重要的非数值运算,本文在分析了当前几种主要的匹配算法思想的基础上,提出了一种新的改进 算法.降低了匹配算法的时间复杂度,提高了算法效率。

    算法分析骑士巡游问题 C++实现

    算法分析中的骑士巡游问题实现,可以设置骑士最初在棋盘中的位置,算法时间复杂度最大值为N的立方。

    论文研究-EPZS运动估计算法的分析及改进.pdf

    在分析研究H.264视频编码标准推荐的运动估计核心算法EPZS的基础上,针对该算法运动估计实时性不足的缺点,提出一种对EPZS算法进行起始搜索窗口中心点和计算终止条件判断标准的改进方法,在H.264编码器的参考模型JM...

    数据结构实验1 JAVA程序设计基础及算法设计.doc

    (4) 熟悉算法的描述方法、算法时间复杂度的分析和计算方法 (5) 理解数据和算法的基本概念 二、 实验内容: 1、 采用二维数据输出杨辉三角形,二维数据的结构如图1所示: 0 1 2 3 4 5 1 1 1 1 2 1...

    计算机二级公共基础知识

    1.算法的概念、算法时间复杂度及空间复杂度的概念 2.数据结构的定义、数据逻辑结构及物理结构的定义 3.栈的定义及其运算、线性链表的存储方式 4.树与二叉树的概念、二叉树的基本性质、完全二叉树的概念、二叉树...

    论文研究-快速的属性约简算法.pdf

    为了提高约简效率,在分析不可分辨关系和基数排序特点的基础上,提出了一种时间复杂度为O(|C||U|)的求核算法。然后,运用改进的属性重要度作为启发信息,得到一种快速的属性约简算法,时间复杂度为O(|C|2|U|)。...

    论文研究-一种运用游程编码的大数模乘算法.pdf

    为了优化提高大整数模乘的运算效率,基于以空间换时间的思想,在改进滑动窗口编码的基础上,提出了一种新颖的游程编码,并在此基础上,设计了一种快速大数模乘的实现算法,分析了该算法的时间复杂度和空间复杂度。...

    基础的数据结构与算法以及一些算法题.zip

    算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、...

    论文研究-一种新的商务名片的快速二值化算法.pdf

    而现有的二值化算法时间复杂度高,并且缺乏针对性。提出了一种专门针对商务名片的快速二值化算法,该算法利用颜色模型,通过优化带权误差平方和目标函数找到最优阈值,并给出一个快速迭代算法。经过大量实验证明,...

    计算机算法分析与设计(共33张PPT).pptx

    学习目标 掌握算法分析与设计的基本理论 掌握进行算法分析与设计的基本方法(时间、空间复杂度分析,算法正确性的证明) 掌握计算机领域中常用的非数值计算方法,并学会用这些算法解决实际问题 计算机算法分析与...

    字符串匹配算法Sunday的改进

    字符串的模式匹配应用十分广泛,在信息的搜索查询等方面具有重要作用,研究串...最后得出结论:在实际应用中,坏字符大量存在的情况下,改进算法的最优时间复杂度可达O(n/m),在同一时间复杂度下,比Sunday算法效率提高25~50%.

Global site tag (gtag.js) - Google Analytics