我们进行编程,无非就是对数据的操作打交道。数据结构与算法就是为了在设计程序的时候更省时、更省内存的处理数据。
一、复杂度
我们怎么才能决定哪个程序设计的更省时、省位置?
如果仅仅通过程序开始到结束运行时间的差额和内存使用情况来计算会出现以下几个问题。
- 硬件依赖:当同一个程序运行在不同配置的电脑电脑时运行的时间可能不同。
- 测试结果需要事后才能计算:一般情况下,我们的程序希望在伪码阶段就能够预测程序的性能。
- 测试结果受原始数据特性影响大:举个例子,在1~100中查找一个数组,如果按照暴力的解法,而恰恰需要查找的数据为1,那么能说明这个方法的效率很高吗?
因此,我们需要使用复杂度来表示一个程序的性能如何。
复杂度分为
- 时间复杂度(复杂度越高,耗时越久):记录多少步完成(一般只看for循环有多少)
- 空间复杂度(复杂度越高,占用内存越多):记录完成程序定义的基本数据类型数量
复杂度用大O标记法来表示
时间复杂度是用来表示程序运行时间随着数据量增长的变化趋势
表示方法:
- 如果复杂度为常量,则用O(1)表示
- 如果复杂度为对数或线性即 O(logN)、O(N)则,省略常量和系数
- 如果复杂度为指数即O(N2),则省略常量、系数、对数、线性
总之,大O记法,只保留最大趋势公式
指数 > 线性 > 对数 > 常量
摩尔定律:当价格不变时,集成电路上可容纳的元器件的数目,每过18 - 24个月会增长一倍。换句话说,每过18 - 24个月同样大小的芯片里可存储的数据量将翻一倍,因此我们除从事嵌入式开发或单片机开发,不需要考虑空间复杂度
二、二分法
假如我们从0-100数字中猜一个数,常规思路就是从1数到100,这样的话效率低。
如果我们先猜中间值,如果比中间值大,那么我们取中间值到100的中间值,按照这种方法推。我们仅需要log100次就可以查找到那个值。
二分法就是用来解决查找排序数组或集合的算法设计思路。
eg:给定任意数组,查找一个目标值是否在数组中。如果存在给出索引。
public static int