透彻理解时间复杂度

本文深入探讨了时间复杂度的概念,强调了它在衡量算法效率中的重要性。介绍了算法定义、衡量标准、时间成本的衡量方法,特别是通过RAM模型模拟算法运行。此外,还阐述了复杂度与输入规模的关系,以及如何分析最好和最坏情况下的时间复杂度。文章以排序算法为例,展示了如何使用渐近表示法分析算法的时间复杂度,指出在评估算法时通常关注最坏情况的时间复杂度。
摘要由CSDN通过智能技术生成

透彻理解时间复杂度

若觉得本文写得还可以,请多多关注本人所作书籍《C++语法详解》电子工业出版社出版,网盘地址:
https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文是本人所作文章《透彻理解渐近表示法》的后续,若读者不怎么理解渐近表示法可参该文章

时间复杂度是用来衡量算法好坏的,因此,首先需要对算法及其衡量标准作一讲解

一、算法的定义

1、算法是为解决某一问题而设计的一个指令的序列。算法应具有以下特点:

  • 输入和输出:这是明显的,通常,一个问题需要根据期望的输入通过算法产生一个期望的输出作为结果,也就是说,算法用于求解输入和输出之间的关系。
  • 正确性:对每个输入,算法都应以正确的输出停机。当然,这并不代表不正确的算法就没有用,若算法的错误率可控有时也是有用的。
  • 有限性:很明显,任意算法都应在执行有限次数之后终止运行并给出输出。若一个算法具有算法的所有其他特点,但缺少有限性,则这个算法被叫做计算方法,计算方法有时也是有用的。
  • 确定性和可行性:是指算法应由若干语义明确的基本操作组成,且每一基本操作在对应的计算机模型中是可兑现的。

2、针对一个问题需要先设计出一个算法(注:一个问题通常会有多种算法),然后还需证明该算法的正确性、有限性,最后还要分析这个算法的时间成本和空间成本,因此,算法包括如下几个方面:

  • 算法设计:算法设计为《数据结构与算法》课程的主要内容。
  • 算法证明(证明其正确性):算法正确性的证明可使用数学归纳法进行,算法证明不是本文的内容,因此,本文不作介绍。
  • 算法分析(分析其效率):算法分析则需要使用前文介绍的渐近表示法以及本文介绍的时间复杂度,因此,需要把一个算法抽象为能使用数学表示的渐近表示法来分析其时间复杂度,从而判断出算法的优劣,本文主要讲解算法分析的问题。
  • 每个算法都需对其进行证明(正确性)和分析(效率),因此,在学习设计算法之前,应先学习怎样证明和分析一个算法

二、衡量(评判)算法的思维

1、衡量算法的基本思维

  • 无关原则:衡量算法好坏的一个基本原则就是,算法的好坏需要与使用的语言、计算机、操作系统等无关,只与算法本身及其输入的规模有关。比如,若算法1比算法2更快,则无论算法1和算法2使用何种语言实现,无论在什么计算机、操作系统上运行,算法1都应比算法2更快,再如,某算法很费时,则该算法无论使用何种语言实现,无论在什么计算机、操作系统上运行都很费时,除非对该算法本身进行改良。
  • 近似原则:一个算法很难计算出精确的成本(或效率),我们也不需要算法的精确成本,因为在对算法进行分析时,通常只需要知道以下信息就可以了。
    • 算法的大致成本(近似成本)。在日常生活中也经常使用近似成本,比如,需要在24小时之内从重庆到达北京,最快的选择就是乘飞机,此时,我们不需要飞机的精确飞行时间,只需要知道飞行时间不会超过24小时就可以了。对算法进行分析时,通常就只需要知道这种大致的很粗糙的成本就可以了,没必要计算出精确成本。
    • 算法成本的大致变化趋势。关于这一点,在后文以及渐近表示法中有所讲解。
    • 在算法间进行比较。此时更没必要知道算法的精确成本,比如,从重庆到北京,我们完全可以不用知道(也没必要计算出)步行和乘火车的精确速度,就能比较出乘火车肯定更快,算法比较的思维与此类似。
    • 从以上分析可见,对算法的分析与渐近表示法对函数的分析是一致的,因此,算法通常使用渐近表示法进行分析。

2、衡量算法的方法:使用模型模拟

  • 一个算法的成本需要上机实际测试才能知道,但我们不可能也没必要对每个算法都进行上机实际测试,并且不同计算机对同一算法测试出来的成本也不一定相同。取而代之的是,使用一个虚拟的模型模拟算法的运行,并以模拟的结果来评判一个算法的成本,模拟可以使对算法的衡量与使用的语言、计算机、操作系统等无关。摸拟也是现实生活中经常使用的一种方法。

3、分析算法的关键及工具

  • 通常使用渐近表示法来分析算法的好坏,因此,分析(衡量)算法的关键是需要能求出一个关于算法成本的函数T(n),然后将T(n)使用相应的渐近表示法表示,再使用渐近表示法进行分析。

4、算法衡量的标准的抽象过程

  • 可以使用很多种标准来衡量一个算法的好坏,比如,可以使用算法的执行时间、所占存储空间、算法所占字符长度、算法所需指令数等不同标准来对算法的好坏程度进行衡量。算法通常使用效率(或成本)来衡量其好坏程度,效率通常又使用时间成本或空间(即,存储空间)成本对其进行衡量,时间或空间成本通常又使用渐近表示法(其中,更常使用大O表示法)来进行近似的分析。也就是说,对一个算法的评判,最终使用的是渐近表示法从时间或空间方面对算法的效率进行近似的衡量。通常,算法的时间成本比空间成本更重要,因此,衡量一个算法的好坏,关键在于对算法时间成本的衡量。图1为对算法衡量标准的抽象过程
  • 在这里插入图片描述

三、时间成本的衡量方法与RAM模型

1、时间成本主要与每条指令的执行时间及执行每条指令的次数有关,只需把二者相乘就能得到某条指令的总执行时间,然后把所有指令的总执行时间相加,就得到算法的运行时间。但是,精确的计算却是很复杂的、不现实的、甚至不可能完成的,因此,对算法时间成本的衡量,通常使用一种模型对其进行模拟,然后以模拟的结果作为算法的时间成本。

2、算法的运行时间T(n)的求解思维

  • 方法一:找出算法中最费时的一个或多个关键操作,使用这些关键操作计算出算法的T(n),使用此方法的关键是要能找到影响算法运行时间的关键操作,该方法忽略了关键操作之外的其他操作,需要非常谨慎,并且误差较大。该方法的原理如下:

    • 对时间成本的分析不需要精确的时间,通常,算法中一小部分执行最频繁的指令决定了算法的总运行时间。
    • 由于运行时间最终需要使用大O表示法进行分析,由大O表示法的加法性质可知,大O表示法只取决于表达式中最强的那一项,而这一项,通常是算法中的关键步骤决定的。
  • 方法二:使用RAM模型的总步数计算T(n),使用该方法可以统计算法的所有操作。RAM及其步数的讲解,见后文

3、算法通常使用RAM机(Random Access Machine,随机存取机)对其进行摸拟,由于是摸拟的真实计算机,因此,需对RAM模型的指令及其成本进行设计

4、RAM模型指令的设计原则

  • 通常,RAM模型应包含真实计算机中的常见指令,比如,应包含算术指令(如加、减、乘、除、取余、取整等)、数据移动指令(装入、存储、复制)、控制指令(条件与无条件转移、子程序调用、返回等),但是不应对RAM模型进行随意的设计,比如,不应为RAM模型设计一条排序指令,因为,现实计算机没有这样的指令。

5、RAM模型时间成本的设计原则

  • 假设每条RAM指令的执行时间都为常量。没有必要知道每条指令的具体执行时间,只需要知道是常量就可以了,因为,算法的运行时间最后通常使用的是大O表示法进行分析,而大O表示法最终会把常量置为1,因此,没有必要知道每条指令的精确执行时间。

6、RAM模型具有以下特点:

  • 每个单一操作对应一个时间步(简称步),比如+、-、*、if、函数调用等都是这样的单一操作,这里的时间步与算法定义中的基本操作相对应,也就是说,一个时间步类似于一个基本操作,时间步的定义并不是很精确,后文会对时间步作进一步的说明。
  • 循环和子程序不被视为是一个单一操作,它们是多个单一操作组成的复合操作。
  • 每次内存访问恰好用去一个时间步
  • 内存是无限的,需要多少内存就有多少内存。

7、对RAM模型的进一步说明

  • RAM模型中的指令没有并发操作,指令需一条接着一条地执行。
  • RAM模型的数据类型有整型和浮点型,通常不关心精度问题。
  • RAM模型中的指令有一些灰色区域,应尽量避免这样的灰色区域。比如,指数运算 x y x^y xy,当x和y都是实数时,计算 x y x^y xy需若干条指令,但若对x和y给出一些限制, x y x^y xy又可表示为移位运算,比如,将一个整数向左移一位等价于将该数乘以2,左移k位等价于将该整数乘 2 k 2^ k 2<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值