本文的博主也就是本人也算是根正苗红的计算机科学专业,从进入大学开始就一直对算法耳濡目染但从未认真研究及学习。时至今日尽管已经能够独立完成一些项目,但仍觉与正规军相差甚远。其根本原因可能就是基本功不够扎实,于是决心从今日起潜心算法,日日更新。
本笔记的内容来自对网络资料,书籍或者其他博客的总结及个人化(用自己的话再白话一遍),笔记的主要学习规划线路参考Carl大神的代码随想录,这也是在我苦心搜集和寻找之后觉得能够让我从基础开始跟随的最优选择。本人算法小白,如有大佬路过请轻喷。
从如下六点进行分析:
- 究竟什么是时间复杂度
’条条大路通罗马‘,编程也是一样,实现同一功能的写法可以有多种,但是如何评判哪一种是更好的呢?时间复杂度便是评判标准之一。时间复杂度简而言之就是你写出来的程序运行时间效率的估算方式。为什么是估算呢?
这里博主认为编写的算法的运行时间不仅仅受算法结构和质量本身的影响,也会受到计算机硬件性能的影响。因此不同计算机上相同结构和质量的算法也有可能具有不同的运行时间 (即运行单元的运行时间在不同的硬件上可能不同)。因此使用函数形式对于运行时间进行估算,统一相同算法在不同计算机上的运行时间效率是很有必要的。
通常来说我们可以把估算计算过程的大概趋势抽象成四种类型,能够对应四种不同场景:
以下场景例子参考: 一套图 搞懂“时间复杂度”
线性类型
对数类型
常数类型
平方类型
事实上场景中的n就是我们之前所提到的操作单元数量即公式中的操作次数。经过上面的四个场景的介绍,大概已经清楚算法的执行方式大体上就上述的四种场景,因此我们可以用这四种类型的公式来对时间复杂度进行抽象的估算。
- 什么是大O
渐进时间复杂度用大写O来表示,所以也被称为大O表示法。
对于这个渐进时间复杂度的定义其实很好理解,T(n)/ f(n)的极限值为不等于零的常数,证明了T (n)和f (n)这两个函数的值的变化速度是同一个数量级的 (同阶函数,为1是等价函数),若T (n)的变化速度远大于或远小于f (n)则T(n)/ f(n)的极限值应为无穷或0 (大家可以去看下对于判断两个函数的高阶,低阶,同阶和等价的概念)。
既然函数同阶那么我们就可以利用这个同阶的函数来代表这一类问题的时间复杂度,即统一时间效率的评估标准(反正我们也不需要算出确切的时间,都是在进行估算)。
推导出时间复杂度呢?有如下几个原则:
Carl大神对于大O的另一个说明是目前我们常说的时间复杂度是指算法在一般情况下的时间效率:
- 不同数据规模的差异
事实上上述的情况都是在考虑数据量趋近于无穷的情况下,Carl大神给出了不理想情况即不同数据规模下的一些差异。
如下图中可以看出不同算法的时间复杂度在不同数据输入规模下的差异。
在决定使用哪些算法的时候,不是时间复杂越低的越好(因为简化后的时间复杂度忽略了常数项等等),要考虑数据规模,如果数据规模很小甚至可以用O(n^2)的算法比O(n)的更合适(在有常数项的时候)。
面试中说道算法的时间复杂度是多少指的都是一般情况。但是如果面试官和我们深入探讨一个算法的实现以及性能的时候,就要时刻想着数据用例的不一样,时间复杂度也是不同的,这一点是一定要注意的。
- 复杂表达式的化简
有如下几个原则,刚才博主有提到实际上是一样的,这边看不懂可以回看刚刚的场景示例:
中的log是以什么为底
平时说这个算法的时间复杂度是logn的,那么一定是log 以2为底n的对数么?
其实不然,也可以是以10为底n的对数,也可以是以20为底n的对数,但我们统一说 logn,也就是忽略底数的描述。