前言
最近决定重学数据结构与算法,同时结合LeetCode实践来刻意练习。持续专注不变的底层知识。
以下根据《重学数据结构和算法》学习笔记整理和思考总结。
01.复杂度:如何衡量程序运行的效率?
复杂度分为:时间复杂度、空间复杂度。
时间复杂度的计算和代码的结构,代码的执行次数有关系。
空间复杂度的计算和数据结构,存储资源有关系。
复杂度和常系数无关如:O(n)、O(2n)、O(n/2)都表示O(n)复杂度
多个复杂度相加,取高次项复杂度为最终结果,如:O(n3+n2+n)那么这个复杂度就是O(n^3)
常见的一些时间复杂度有:
(1)对一个数组遍历循环,若数组长度为n,那么时间复杂度为O(n)。
(2)嵌套遍历,若外层遍历n次,内层遍历m次,则时间复杂度为O(m*n)。
(3)若两个遍历不是嵌套的,还是顺序的,那么时间复杂度依然是O(n)+O(n) = O(2n) = O(n),最终依然为O(n)。
(4)若n和程序执行的次数无关,那么时间复杂度始终为O(1);比如针对一个长度为n的字符串直接进行输出操作,不管长度为多长,始终只需输出一次。
(5)O(1)也是表示一个特殊的复杂度,为某个任务通过有限可数的资源即可完成。与输入的数量n无关。
优化时间复杂度很重要,处理10万的数据,程序结构定下的不同的时间复杂度,让计算机计算的次数是有天壤之别的。
我们给出一些经验性的结论:
- 一个顺序结构的代码,时间复杂度是 O(1)。
- 二分查找,或者更通用地说是采用分而治之的二分策略,时间复杂度都是 O(logn)。
- 一个简单的 for 循环,时间复杂度是 O(n)。
- 两个顺序执行的 for 循环,时间复杂度是 O(n)+O(n)=O(2n),其实也是 O(n)。
- 两个嵌套的 for 循环,时间复杂度是 O(n²)。
高手进阶:写完代码后能评估代码的复杂度,并能进行优化,追求极客精神。
02 数据结构:将“昂贵”的时间复杂度转换成廉价的空间复杂度
降低时间复杂度方法有:递归、二分法、排序法、动态规划。
降低空间复杂度:围绕数据结构。
- 数组 数组长度决定,空间复杂度o(n)
- 递归 根据递归的深度可达到 o(n)
- ……
小结:关于数据结构如何降低空间复杂度,可以根据LeetCode中爬楼梯的算法中的官方解答来进一步了解
程序优化最核心思路:
- 暴力解法。有没有任何时间、空间约束下,完成代码的任务开发。
- 无效操作处理。将代码中的无效计算、无效存储剔除,降低时间或空间的复杂度。
- 时空转换。设计合理的数据结构,完成时间复杂度向空间复杂度的转移。
参考资料:
如何理解算法时间复杂度的表示法,例如 O(n²)、O(n)、O(1)、O(nlogn) 等?