【书籍阅读】《算法图解》——全书阅读笔记

第一章 算法简介

1.1 二分查找

1.2 大O表示法

  • 除了最糟情况,还应该考虑平均情况的运行时间
大O运行时间算法
O(logn)二分查找
O(n)简单查找
O(n*logn)快速排序
O(n²)选择排序
O(n!)旅行商问题
  • 算法的速度指的是操作数的增速
  • 表示随着输入的增加,其运行时间将以什么样的速度增加

第二章 选择排序

2.1 数组和链表

数组链表
读取O(1)O(n)
插入O(n)O(1)
删除O(n)O(1)

2.2 选择排序

  • 两次循环

第三章 递归

3.1 递归

  • “如果使用循环,程序的性能可能更高;如果使用递归,程序可能更容易理解。”

3.2 基线条件和递归条件

  • 递归条件:自己调用自己
  • 基线条件:不再调用自己

3.3 栈

  • 调用栈(call stack)
  • 两种操作:压入和弹出
  • 所有函数调用都进入调用栈

第四章 快速排序

4.1 分而治之

  • 分而治之(divide and conquer),D&C算法是一种解决问题的思路
  • D&C包括
    1. 找出基线条件,这种条件必须尽可能简单
    2. 不断将问题分解(或者说缩小规模),直到符合基线条件

4.2 快速排序

  • C语言中qsort实现的就是快速排序
  • 快速排序使用了D&C
  • 归纳证明,一种证明算法行之有效的方式
    • 基线条件,对空或者一个元素是有效的
    • 归纳条件,对两个元素有效,对三个元素有效…

image-20221012212626536

4.3 再谈大O表示法

  • 大O表示法中,n实际上是这样的

image-20221012213705175

  • 快速算法最快是O(nlogn),最糟糕是O(n²)
  • 只要每次随机选择元素作为基准值,最佳情况就是平均情况,为O(nlogn)
  • 快速算法是最快的排序算法之一,也是D&C典范

第五章 散列表

5.1 散列函数

  • 将输入映射到数字
    • 散列函数总是将同样的输入映射到相同的索引
    • 散列函数将不同的输入映射到不同的索引
    • 散列函数知道数组的大小,只返回有效的索引
  • 散列表也使用数组来存储数据,因此其获取元素的速度和数组一样快
  • 散列表由键和值组成
  • Python提供的散列表实现为字典

image-20221013203635106

  • 散列表适用于
    • 模拟映射关系
    • 防止重复
    • 缓存/记住数据,以免服务器再通过处理来生成它们

5.2 冲突

  • 冲突:给两个键分配的位置相同
  • 如果两个键映射到了同一个位置,就在这个位置存储一个链表,这样效率会不高,所以选择一个好的散列函数很重要

5.3 性能

image-20221013204541854

  • 提升性能需要:
    • 较低的填装因子(散列表中有多少位置使用),一旦大于0.7就调整散列表的长度
    • 良好的散列函数,SHA函数

第六章 广度优先搜索

6.1 图介绍

  • 图由节点(node)和边(edge)组成

image-20221013211003483

image-20221013211727339

6.2 广度优先搜索

  • 解决最短路径问题的算法被称为广度优先搜索,BFS
  • 广度优先搜索是一种用于图的查找算法,可帮助回答两类问题
    1. 从节点A出发,有前往节点B的路径吗?(在你的人际网中,有芒果经销商吗?)
    2. 从节点A出发,前往节点B的哪条路径最短?(哪个芒果经销商与你的关系最近?)

6.3 队列

  • 队列:可以按添加顺序进行操作(否则难以找到最短的路径)
  • 两种操作:入队和出队
  • 在Python中,使用函数deque来创建一个双端队列
  • 队列:先进先出;栈:后进先出

image-20221013211656460

6.4 实现

  • 这种映射关系可以用散列表来处理
  • 避免死循环,检查一个后,应进行记录(我的朋友是朋友的朋友)
  • 广度优先搜索的运行时间为O(人数+边数),O(V+E),V为顶点数,E为边数

image-20221029171625425

第七章 狄克斯特拉算法

7.1 狄克斯特拉算法

步骤:

  1. 找出“最便宜”的节点,即可在最短时间内到达的节点
  2. 更新该节点的邻居的开销
  3. 重复这个过程,直到对图中的每个节点都这样做了
  4. 计算最终路径

7.2 加权图

image-20221013232614031

7.3 负权边

image-20221013233002128

  • 如果有负权边,就不能使用狄克斯特拉算法,因为狄克斯特拉算法假设:考虑过的节点,在之后不会有更短的路径到达
  • 处理有负权边的图,可以使用贝尔曼-福德算法

7.4 实现

  • 重要:狄克斯特拉算法只适用于有向无环图DAG
  • 关键理念:找出图中最便宜的节点,并确保没有到该节点的更便宜的路径

image-20221029171731126

第八章 贪婪算法

8.1 贪婪算法

  • 每步都采取最优的做法,即每步都是局部最优解,最终得到的就是全局最优解

8.2 近似算法

优劣的判断标准:

  • 速度有多快

  • 得到的近似解与最优解的接近程度

  • 集合类似于列表,只是不能包括重复的元素;可以做并集、交集和差集等运算

8.3 NP完全问题

  • 元素较少时算法的运行速度非常快,但随着元素数量的增加,速度会变得非常慢
  • 涉及“所有组合”的问题通常是NP完全问题
  • 不能将问题分成小问题,必须考虑各种可能的情况,这可能是NP完全问题
  • 如果问题涉及序列(如旅行商问题中的城市序列)且难以解决,它可能就是NP完全问题
  • 如果问题涉及集合(如广播台集合)且难以解决,它可能就是NP完全问题
  • 如果问题可转换为集合覆盖问题或旅行商问题,那它肯定是NP完全问题

第九章 动态规划

9.1 动态规划

  • 先解决小问题,再逐步解决大问题
  • 需要在给定约束条件下优化某种指标时,动态规划很有用
  • 仅当每个子问题都是离散的,即不依赖于其他子问题时,动态规划才管用

9.2 注意点

  • 每种动态规划解决方案都涉及网格
  • 单元格中的值通常就是要优化的值,背包问题中,就是商品的价值
  • 每个单元格都是一个子问题,所有需要考虑如何将问题分成子问题

9.3 绘制网格

  • 单元格中的值是什么?
  • 如何将这个问题划分为子问题?
  • 网格的坐标轴是什么?

第十章 K最近邻算法

10.1 KNN

  • 分类:编组
  • 回归:预测结果(如一个数字)

10.2 特征提取

  • 距离公式
  • 余弦相似度

第十一章 接下来如何做

11.1 树

  • 对于每个节点,左子节点的值都比它小,而右子节点的值都比它大
  • 二叉树存在一些缺点,比如不能随机访问
  • 处于平衡状态的特殊二叉查找树:红黑树

11.2 反向索引

  • 一个散列表,将单词映射到包含它的页面,就是反向索引
  • 常用于创建搜索引擎

11.3 并行算法

  • 并行性管理开销:合并结果也是需要时间的
  • 负载均衡:均匀地分配工作

11.4 分布式算法

  • 映射(map):将一个数组转换为另一个数组
  • 归并(reduce):将一个数组转换为一个元素
  • MapReduce使用这两个概念在多台计算机上执行数据查询

11.5 布隆过滤器

  • 涉及庞大的集合,需要判断一个元素是否属于其中
  • 是一种概率型数据结构
  • 得到的答案很有可能是正确的
  • 占用的存储空间很少
  • 适合用于不要求答案绝对准确的情况

11.6 线性规划

  • 用于在给定约束条件下最大限度地改善指定的指标
  • 所有图算法都可以使用线性规划来实现
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值