【算法】《算法图解》简单小结
算法基础
第1章 算法简介
- 算法是一组完成任务的指令
- 简单查找->二分查找
- 大O表示法--旅行商问题O(N!)
第2章 选择排序
- 内存的工作原理-带有存储地址信息的抽屉合集
- 数组和链表-各有优缺点
- 数组:随机读取更快
- 链表:插入、删除更快
- 选择排序:O(N^2)
- 思路:遍历n次,每次选出最值
- 算法结构:for...for...嵌套
第3章 递归
- 递归
- 使用循环,性能可能更高;使用递归,可读性更好
- 基线条件和递归条件
- 递归条件(recursive case): 函数调用自己的条件
- 基线条件(base case): 结束递归的条件
- 栈
- 先进后出 LIFO
- 所有函数调用都进入调用栈
- 防止栈溢出
基本算法
第4章 快速排序
- 分而治之(D&C)-递归式
- Step1:找出尽可能简单的基线条件
- Step2:不断将问题分解,直到符合基线条件
- 快速排序
- 思路:分治法,递归,O(NlogN)
- python:直接取[更小值合集]+基准值+[更大值合集];然后递归两个合集
- 其他语言:交换ij直到相遇,则交换相遇元素与基准值;然后递归两侧数组
- 再谈大O表示法
- 合并排序:分-治,O(NlogN)
- 一直划分,直到最小单元,之后开始向上合并
- 相同O,快速排序更快
- 合并排序:分-治,O(NlogN)
第5章 散列表
- 散列表
- hash table/字典
- 键值对构成的数据结构
- 散列表使用数组存储元素
- 散列表的查找/插入/删掉都很快
- 散列函数
- 结果一致性
- 应将不同输入映射到不同数字(最好)
- 散列表的应用
- 查找
- 防止重复
- 缓存/记住数据,以免服务器再次生成
- 冲突与性能
- 更低的填装因子(<0.7):利用占比,度量散列表中有多少位置是空的
- 良好的散列函数:尽可能均匀分布
第6章 广度优先搜索
- 图
- 模拟一组连接
- 由节点node和边edge组成
- 邻居:直接相连的节点,起点本位,被指向的是起点的邻居
- 有向图/无向图
- 树:一种特殊的图
- 图查找:广度优先搜索
- 解决:从A到B是否有路径;最短路径是?
- BFS: 先查找一度关系,再查找二度关系
- 按添加顺序查找:先添加一度,后添加二度
- 队列
- 先进先出 FIFO
- 图实现
- 散列表:从一个节点映射到所有邻居;无序
- 算法:记录已查;检查之前要先判断是否已查
- O(人数+边数),O(V+E)
第7章 狄克斯特拉算法
- 辨析
- BFS:非加权图中查找最短路径
- 狄克斯特拉算法:加权图中查找最短路径
- 应用条件
- 有向无环图
- 绕环路径不可能是最短路径
- 无向图:每条边都是一个环
- 没有负权边
- D算法:确保到找出的最便宜节点没有更便宜路径
- 负权边请用贝尔曼-福德算法
- 有向无环图
- 步骤
- 找出最便宜节点
- 更新邻居cost
- 获取cost和邻居
- 遍历邻居:cost小不动;cost大,经node小:更新cost和父
- 标记node为已处理
- 重复,遍历所有节点
- 回溯路径
- 算法实现
- 准备3个散列表:
- 图;cost;父表
- 权重表示:二维字典(python)
- 无穷大表示:float("inf")
- 另表:记录处理过的节点
- 准备3个散列表:
第8章 贪婪算法(近似解)
- 核心思路
- 每一步取局部最优解,以获得全局最优解
- 不一定任何情况都有效,但易于实现
- 贪婪算法例子:BFS、狄克斯特拉算法..
- 背包问题-贪婪算法版
- 背包最优解:DP,贪婪不行
- 但贪婪依然能获得一个非常近的解,且易于实现
- NP完全问题
- 特征
- 需要计算所有解,并从中选出最小/最短的那个
- 没有捷径,最好用近似求解
- 经典NP完全问题例子
- 集合覆盖问题
- 旅行商问题
- 识别NP完全问题
- 慢(元素越多,速度越慢)
- 需遍历(涉及“所有组合”)
- 与两种经典NP完全问题相符或可转化为其一(涉及序列/集合,且难以解决)
- 用近似算法解决NP完全问题
- 贪心:找一个当前的局部最优解,重复,直到完全覆盖问题
- 特征
第9章 动态规划(最优解)
- DP
- 先解决子问题,再逐步解决大问题
- 公式:
- cell[i][j] = Max
- PD-背包问题FAQ
- 不能只取商品的一部分(贪心可以)
- 严格按公式取最优解,而不是自己心算,容易错
- 商品之间离散,不相互依赖
- 面向2个子背包合并 (子背包可含多个背包嵌套)
- 最优解可能是背包不满的情况
- 最长公共子串:
- 相同,左上角+1;不同,设为0
- 最长公共子序列(重复字母个数):
- 相同,左上角+1;不同,继承上/左中的较大值
进阶算法
第10章 K最近邻算法
- KNN->推荐算法
- 对比N个最近的邻居来进行分类
- 两个核心:分类和回归
- 分类:编组
- 回归:预测结果
- 特征抽取
- 将物品转换为可量化的数字
- 挑选合适的特征:主题相关;不偏不倚
- eg.水果:颜色/个头;电影:不同类型片的打分;...
- 相似度计算
- 毕达哥拉斯公式:sqar((a1-a1)^2 +..+ (x1-x2)^2)
- 余弦相似度:不计算矢量距离,而是比较角度
- 归一化处理:当打分用户的标准不同时,取平均,并对打分进行调整
- 加权重:当某些用户的评分更重要时
- 其他机器学习算法
- OCR光学字符识别
- 基于KNN算法
- 首先浏览大量数字图像并提取特征(训练);遇到新图像时提取特征并找出最近邻居
- OCR常见特征:线段,点,曲线等
- 类似算法:语音识别,人脸识别
- 垃圾邮件过滤器
- 朴素贝叶斯分类器
- 仍是先训练,后对新邮件进行识别分类
- 预测股票市场
- OCR光学字符识别
第11章 接下来如何做(其他算法)
- 二叉查找树(binary search tree)
- 每个节点,左小右大
- 查找/插入/删除:O(logN)
- 插、删快,但不能随机访问
- 红黑树:处于平衡的特殊二叉树
- B树:特殊二叉树,数据库常用
- 反向索引
- key为单词,value为包含该单词的页面
- 一种很有用的数据结构,用来创建搜索引擎
- 傅里叶变换
- 非常适合用于处理信号
- 常见应用:MP3/JPG压缩;地震预测;DNA分析;音乐识别
- 并行算法
- 可扩展性和海量数据处理,多核并行
- 速度的提升非线性
- 并行性管理开销
- 负载均衡
- MapReduce
- 分布式算法:映射(map)+归并(reduce)
- 通过开源工具Apache Hadoop使用
- 映射函数:将一个数组转换为另一个数组
- 归并函数:将一个数组转为一个元素
- 概率型算法
- 判断给定元素是否包含在一个集合中:散列表
- 但是当数据集很大时,不妥
- 布隆过滤器
- 一种概率型数据结构
- 答案“很可能正确”
- 可能出现错报,不可能出现漏报
- 占用的存储空间少,适用于不要求答案绝对准确的情况
- HyperLogLog
- 概率型算法
- 同样,不一定准确但八九不离十,内存占用小,
- 判断给定元素是否包含在一个集合中:散列表
- SHA算法
- 安全散列算法SHA
- SHA是散列函数,根据字符串生成另一个字符串
- 应用:比较超大型文件是否相同;单向检查密码(更安全不怕被盗)
- 局部不敏感(局部修改显化)
- 局部敏感的散列算法:Simhash
- 要求:字符串细微修改后,散列值也只存在细微差别
- 应用:判断网页是否已搜索;论文查重;上传文档是否有版权冲突..
- Diffie-Hellman
- 使用"公钥和私钥"对消息进行加密
- 对方发消息时,使用公钥加密,加密后的消息只有私钥能破解
- 优势:双方无需知道加密算法;难破解
- 本算法及其替代者RSA依然被广泛使用
- 线性规划
- 给定约束条件,最大限度改善给定指标值
- 同数学题中的线性规划
- 使用Simplex算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!