数据结构与算法(一)怎么判断算法的好坏
怎么判断算法的好坏
一 评价的的指标
数据结构与算法最直观的目标就是要提高代码的性能。性能体现有两点:快和省。
二 怎么做评价
1.原始的评价方式
那么代码写好了,怎么知道它够不够快,够不够省?
最简单的方法,就是拉出来溜溜。官方点叫事后统计法。直接在把代码跑一遍,统计跑了多久,监控花了多少内存。
这种方法看起来没毛病,不过真正去实践的话,会发现有两个弊端:
1)我在我的电脑(i9处理器)代码跑了1s,我说我写的代码真不错。别人拿过去在他的电脑(i3处理器),代码跑了5s,他说这代码写的真垃圾。
结论就是测试结果很依赖测试环境。
2)我写的算法从头开始找数据,目标数据刚好在第一个,我花一次就找到,别人写的算法从尾巴开始找数据,目标数据刚好在第一个,花了n次找到。我能说我的算法优于别人的吗?目标数据这次刚好在第一个,下次在最后一个呢?
以上的例子可能不太恰当,不过结论是一样的:测试结果很依赖具体的测试数据。
2.改进的评价的方法–时间复杂度,复杂度
2.1代码的快慢程度–时间复杂度
不妨做个大胆的假设:每行代码执行的时间都一样,为 unit_time。
那么看看代码跑一次一共执行了多少行才得出结果不就可以评判它的快慢程度吗?
这个方法简单粗暴,不管在什么机子上跑都一样,比较公平。
那当测试的规模变化了,怎么去公平的评价呢?
先来看一个规律。
根据改进的评价方法,有人总结了一个规律:所有代码的执行时间 T(n) 与每行代码的执行次数 n 成正比。
简洁点用公式表达这个规律就是:T(n)=O( f(n) )
其中T(n)就是代码执行的时间,n代表数据规模的大小,f(n)代表每行代码总共执行次数。O代表f(n)与T(n)成正比关系。
其中O( f(n) )并不是代表代码真正的执行时间,否则用f(n)代码的执行次数去乘以一个固定的单位时间值就可以了,它代表的是代码执行时间随数据规模增长的变化趋势。O( f(n) )就叫做渐进时间复杂度,简称时间复杂度。
第一次看“它代表的是代码执行时间随数据规模增长的变化趋势”这次话,感觉不像是人话,太抽象。那就举个例子:
有两个算法:
算法A的相对时间规模是T(n)= 100n,时间复杂度是O(n)
算法B的相对时间规模是T(n)= 5n^2,时间复杂度是O(n ^ 2)
那哪个算法比较快?
这个问题其实其实没有肯定的答案,测试结果受测试数据规模的影响,
当n=1时,算法A跑100次,算法B跑5次;
当n=1 00时,算法A跑1万次,算法B跑5万次。
所以要想摆脱测试结果规模的影响做出评判,就得用一个指标来表示随着测试数据规模的增长,代码执行时间是怎么变化的。这样就可以分析在不同的应用场合采样什么样的算法比较合适。
怎么分析时间复杂度
总的原则,就是“成大事不拘小节”,只关注重点部分。具体怎么做的呢?
1)如果运行时间是常数量级,用常数1表示;
例如 T(n) = 2------------------------T(n) = O(1)
2)只保留时间函数中的最高阶项,同时省去最高阶项前面的系数。
例如 T(n) = 0.5n^2 + 0.5n-----------------T(n)= n^2
常见的时间复杂度
1)O(1)
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行代码,其时间复杂度也是O(1)。
其实这种情况就是代码不受测试数据的影响,想知道代码的快慢比较代码行数即可。
2)O(logn)、O(nlogn)
来看一段代码
i=1; while (i <= n) { i = i * 2; }
这段代码的时间复杂度就是O(logn),至于底数为2,还是3,不重要,因为对数可以相互转换(太纠结的话可以去看看其他教程)。
3) O(m+n)、O(m*n)
这种情况也很简单,有两种数据数据规模,例如两个独立的循环代码块,一个循环m次,一个循环n次,那么时间复杂度就是 O(m+n)
几种时间复杂度增长速度对比
从慢到快依次是:O(1)、O(logn)、O(n)、O(nlogn)、O(n^2)
2.2 代码执行时占用的内存大小–空间复杂度
前面时间复杂度说的是随着测试数据规模的增长,算法执行时间的变化。
对应的,空间复杂度说的是随着测试数据规模的增长,算法存储空间的变化。比如新建一个变量,意味着申请了一块存储空间。分析空间复杂度比时间复杂度简单多了。一般就着几种类型:O(1)、O(n)、O(n2 )。
- 程序员面试过程中,该怎么判断该公司好坏
- 怎么判断特征选择的好坏
- 算法2.分治算法 芯片判断好坏
- 程序员面试过程中,该怎么判断该公司好坏
- 【cs基础】如何判断算法的好坏
- 请问如何检验校验码的正确,并判断算法的好坏。。
- 程序员面试过程中,该怎么判断该公司好坏
- 怎么判断ios越狱
- HR怎么判断潜力的
- UIPanGestureRecognizer上下左右滑动方向判断算法
- 程序员算法之判断序列是否是二叉查找树的后续
- 算法习题9:判断整数序列是不是二元查找树的后序遍历结果
- C# 怎么判断一个窗体打开
- 笔试算法题(29):判断元素范围1到N的数组是否有重复数字 & 计算整数的7倍
- 【转】判断完全平方数的算法
- 深入理解JVM(三)——JVM之判断对象是否存活(引用计数算法、可达性分析算法,最终判定),Eclipse设置GC日志输出,引用
- 数据结构与算法--单源最短路径算法之dijkstra
- 笔试面试算法经典--判断二叉树是否是平衡二叉树(Java)
- 算法提高 素数判断
- 经典算法 | 计算几何 | 判断点是否在多边形内部两个算法