读书笔记--秒懂算法:用常识解读数据结构与算法阅读与记录

大家知道,计算机专业的基础课程之一就是数据结构和算法,最近有机会再次研读了 《秒懂算法:用常识解读数据结构与算法》A Common-Sense Guide to Data Structures and Algorithms ),这本书不像传统那种干巴巴讲数据结构的课程,其语言风格和示例都非常简洁明了,其核心特色是去数学化,通过大量直观的图解和生活中的常识来解释复杂的计算机算法逻辑,值得大家有空翻翻并回顾一下计软件设计开发的基础。以下是该书的主要内容和核心知识点整理,供大家参考。

1. 核心衡量标准:大 O 表示法 (Big O Notation)

用于衡量算法效率的指标主要有时间复杂度和空间复杂度,主要关注时间复杂度,即算法需要的步骤数,书中首先确立了评价代码效率的统一语言。

  • 时间复杂度 :衡量算法运行步数随数据量增长的变化趋势。
    • :常数时间,效率最高,O(1)。
    • :对数时间,如二分查找,O(log(n))。
    • :线性时间,如线性查找,O(n)。
    • :快速排序等高效排序算法,O(n log(n))。
    • :嵌套循环,如冒泡排序、选择排序、插入排序等,O(n2)。
  • 空间复杂度:衡量算法运行过程中额外消耗的存储空间。

2. 基础数据结构

数据结构是数据的组合方式,同样的数据可以有多种组合方式,不同的组织方式,极大地影响代码运行速度,甚至相差几个数量级。书中对比了不同数据结构在读取、查找、插入、删除这四种操作对比:

3. 经典算法分类

算法就是完成特定任务所需的一组操作。书中通过对比展示了常见经典算法的优化过程,具体如下,排序是为了后续查找使用。

  • 排序算法
    • 冒泡/选择/插入排序:基础排序,复杂度通常为 O(n2)。
    • 快速排序 (Quicksort):基于分治思想,平均复杂度为O(n log(n)),是实践中最常用的排序。
  • 查找算法
    • 线性查找:逐个比对。
    • 二分查找:针对有序数组,每次排除一半数据。
  • 递归 (Recursion)
    • 核心:基准情形 (Base Case) + 递归步骤。
    • 风险:栈溢出。
    • 优化:通过动态规划 (Dynamic Programming)记忆化 (Memoization) 解决重复计算。

4. 进阶数据结构

在基础数据结构的基础上引申出多种高级数据结构,常见的如下:

  • 二叉树 (Binary Tree)
    • 二叉搜索树 (BST):左小右大,查找、插入、删除均为O(log(n)) 。
  • 堆 (Heap)
    • 始终能快速找到最大或最小值,常用于优先级队列。
  • 图 (Graph)
    • 用于模拟复杂关系(社交网络、地图)。
    • 广度优先搜索 (BFS):找最短路径。
    • 深度优先搜索 (DFS):探索所有路径。
  • 前缀树 (Trie)
    • 专门用于字符串处理,如自动补全功能。

5. 核心实战建议

书中不仅讲理论,还提供了提升代码质量的实用建议:

  • 代码优化:不要只关注代码行数,更要关注大 O 复杂度。
  • 选择合适的数据结构:这是算法优化的第一步。例如,将数组换成散列表,往往能将算法复杂度降低 。
  • 权衡 (Trade-offs):有时候需要用空间换时间(常见办法),或者用时间换空间,比如分片存储加载,提前算好月度销售额,这样在计算年度销售额时自动使用月度数据。

6. 典型示例列举

这两个示例和这些观点构成了全书的灵魂:用直觉理解逻辑,用逻辑优化性能。

示例一:电话簿查找(解释二分查找 )

这是书中解释算法效率最经典的例子:

  • 场景:如果你要在一部厚厚的电话簿里找一个名字(比如 "张")。
  • 线性查找(普通人思维):从第一页开始往后翻,直到找到为止。如果名字在最后,你要翻几千次,这就是线性时间复杂度 。
  • 二分查找(算法思维):从电话簿的正中间翻开。如果中间的名字是 "M",你知道 "Z" 肯定在后半部分,于是直接撕掉前半部分。重复这个过程,每次都排除掉一半。
  • 结论 :即使电话簿增加一倍(从 1000 页变 2000 页),二分查找也仅仅是多增加 1 步。这直观地展示了为什么 的效率远高于 。
示例二:超市购物清单(解释数组与集合的性能差异)

书中通过这个例子解释了为什么"看似相同"的操作,性能却大相径庭:

  • 场景:你需要记录购物清单。
  • 数组 (Array):你直接把商品写在清单末尾。这很快,步数是1。
  • 集合 (Set):集合要求不能有重复项。所以每次你想写下"苹果"时,必须先从头到尾检查一遍清单里是否已经有了"苹果"。
  • 结论 :在数组末尾插入是 1,但在集合中插入是 O(n)。这个例子告诉读者:为了维持某种数据特征(如唯一性),必须付出性能代价。

7. 核心观点

  • 数据结构决定算法效率:算法不是凭空存在的,它依赖于数据的组织方式(数据结构)。选择正确的数据结构,往往能让复杂的算法问题迎刃而解。
  • 关注"步数"而非"秒数":衡量代码快慢的标准不应该是运行了多少秒(因为硬件不同),而应该是随着数据量 的增长,操作步数是如何增长的。
  • 最坏情况原则:大 O 表示法通常关注"最坏情况"。务实程序员会为最坏的情况做准备,因为那是性能瓶颈所在。
  • 空间与时间的权衡 (Trade-off):有时候为了让程序跑得更快,我们需要消耗更多的内存;反之亦然。没有完美的算法,只有最适合当前场景的算法。

8. 书中金句

  • 大 O 表示法 : "大 O 表示法并不告诉你代码运行的具体秒数,它告诉你的是:当数据量增加时,你的代码会变慢到什么程度。"
  • 数据结构的重要性 : "数据结构不仅是存储数据的方式,它们还是影响程序性能的'形状'。"
  • 代码优化 : "在盲目优化代码之前,先看看你的大 O 复杂度。把一个 的算法改成 ,比任何微小的代码调整都管用。"
  • 关于递归 : "递归是处理复杂问题的优雅方式,但如果你忘了写'基准情形'(Base Case),它就是通往内存崩溃的单程票。"
  • 核心哲学 : "理解算法的常识,比死记硬背公式重要得多。"
相关推荐
你撅嘴真丑2 小时前
第九章-训练参考
算法
烟花落o2 小时前
【数据结构系列01】时间复杂度和空间复杂度:消失的数字
数据结构·算法·leetcode·刷题
㓗冽2 小时前
阵列(二维数组)-基础题79th + 饲料调配(二维数组)-基础题80th + 求小数位数个数(字符串)-基础题81th
数据结构·c++·算法
努力学算法的蒟蒻2 小时前
day86(2.15)——leetcode面试经典150
数据结构·leetcode·面试
fu的博客2 小时前
【数据结构3】带头指针·单向链表实现
数据结构·链表·带头指针
识君啊2 小时前
Java双指针 - 附LeetCode 经典题解
java·算法·leetcode·java基础·双指针
_F_y2 小时前
子序列系列动态规划
算法·动态规划
田里的水稻2 小时前
FA_规划和控制(PC)-A*(规划01)
人工智能·算法·数学建模·机器人·自动驾驶
twilight_4692 小时前
机器学习与模式识别——Logistic算法
人工智能·算法·机器学习