掌握算法5大特性
(运用到程序的解释):
有穷性: 程序要可以执行完,不能进入死循环
确定性: 程序所得的结果就是这个方法定义的,不能要A得B
可行性: 程序可以通过基本运算正常执行成功,不能出现1/0违背数学的情况
有输入:有参数
有输出:有返回值
不符合上述情况的我们可以称作是程序,但不代表它是算法!
时间复杂度
首先从图中了解常用时间复杂度的一个大小:
O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2^n)<O(n!)
从图中很直观可以看到,
O(1) 是最小的,也就是并没有循环
O(logn) 可以了解下二分查找法(折半查找),推导数学公式,来换算成对数log ,即:
n * (½)^k = 1
n * 1/2^k = 1
n = 2^k
log2^n = k
O(n)围绕问题规模n循环一次
O(nlogn)可以了解下归并排序(分治法),在折半的基础上,还要对折半的数据进行遍历
O(n^2) 就是双循环,最常见的递归快排,最差就是n^2
以上即是我们程序开发中最大时间复杂度的承受限度,超过O(n^2) 的程序严格意义上来讲,不算是合格的程序,当然如果遇到n^3及以上的算法,应该如何处理呢,我们可以运用经典思想:空间换时间来实现,处理50万条数据的用时:
有同学可能从单纯的概念中很难结合到程序中,因为程序中往往多变量,多条件,无法直观判断它的时间复杂度,有一个大家需要注意的地方:
只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时算法的时间性能。
即:T(n)=3n^2-5n+10000,常数10000,低阶项5n,高阶项的常系数3均可忽略,那最后其实简化
就是T(n)=O(n^2)
下图是一道C语言的递归题,大家可以试着推导一下,它的时间复杂度,右边是整个的推导过程:
空间复杂度
空间复杂度其实比较好理解,在这里我强调空间复杂度的一个概念,
空间复杂度是对一个算法在运行过程中临时占用的存储空间大小的量度
什么叫临时占用,就是你在算法中突然创建出的空间,如果你传入了一个数组[1,2,3,4,5],这个数组本身已经占用的空间不属于临时占用,比如直插排序,冒泡排序,选择排序,在原有空间基础上进行的排序和空间交换,它的空间复杂度还是O(1),只要理解这个,本质上空间复杂度的求解是非常简单的
总结:
在我的学习过程中,领悟的一个道理,空间和时间是相辅相成的,并没有说鱼和熊掌需要兼得,在整个程序设计阶段,经常存在用 时间换空间 和用 空间换时间 的案例,硬件(内存,磁盘,CPU),开发(代码的循环,数据量的大小)都有可能成为影响整个程序性能的因素,在业务开发中,往往最合适的的方案才是最完美的方案,希望大家可以先思考再实践,不要急于将思路体现在代码中
上图引用:贺立坚老师PDF教材
注:欢迎大家沟通学习,可以但不限于Web,数据结构,操作系统,数据库,中间件等知识