惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Mox的笔记库

细嗦下MLIR的环境搭建 | Mox的笔记库 博客重构:从Hexo到Astro | Mox的笔记库 2026PPoPP MLIR Tutorial学习 | Mox的笔记库 MacOS配置《明日方舟:终末地》 | Mox的笔记库 2025:向内生长 | Mox的笔记库 由mlir::ExecutionEngine引发的跨系统问题 | Mox的笔记库 WSL2配置Cuda-Tile环境记录(未完待续) | Mox的笔记库 Vibe Coding手搓项目记录 | Mox的笔记库 给Debian上包——以DuckDB为例 | Mox的笔记库 UCPD.sys事件存档 | Mox的笔记库 换新电脑之Mac mini M4从购买到配置 | Mox的笔记库 Mac配置MLX-C开发环境 | Mox的笔记库 RISC-V meets RDBMS——RISC-V架构上可运行数据库一览 | Mox的笔记库 DuckDB Sort实现调查 | Mox的笔记库 修复Redis在树莓派5上无法运行的问题 | Mox的笔记库 如何在MLIR中自定义类型并且输出运行 | Mox的笔记库 网站网络结构变更记录 | Mox的笔记库 EDBT25论文阅读:PhoebeDB——A Disk-Based RDBMS Kernel for High-Performance and Cost-Effective OLTP SIGMOD25论文阅读:BPF-DB:——A Kernel-Embedded Transactional Database Management System For eBPF Applications SIGMOD24文章阅读:Query Compilation Without Regrets | Mox的笔记库 论文阅读:Designing an Open Framework for Query Optimization and Compilation Apache Arrow Gandiva项目解析 | Mox的笔记库 VLDB24论文阅读:Cloud-Native Database Systems and Unikernels——Reimagining OS Abstractions for Modern Hardware NoisePage源码分析(未完待续) | Mox的笔记库 VLDB20论文阅读:Mainlining Databases——Supporting Fast Transactional Workloads on Universal Columnar Data File Formats VLDB17论文阅读:Relaxed Operator Fusion for In-Memory Databases:Making Compilation, Vectorization, and Prefetching Work Together At Last 论文阅读:How not to structure your database-backed web applications——a study of performance bugs in the wild SIGMOD24阅读:ROME——Robust Query Optimization via Parallel Multi-Plan Execution 文章阅读:First Past the Post-Evaluating Query Optimization in MongoDB SIGMOD文章阅读:Apache Calcite——A Foundational Framework for Optimized Query Processing Over Heterogeneous Data Sources VLDB23论文阅读:Analyzing the Impact of Cardinality Estimation on Execution Plans in Microsoft SQL Server SIGMOD22论文阅读:Efficient Massively Parallel Join Optimization for Large Queries VLDB论文阅读:Weaving Relations for Cache Performance VLDB22论文阅读:ConnectorX——Accelerating Data Loading From Databases to Dataframes 论文阅读:UniKraft-Fast, Specialized Unikernels the Easy Way 当DuckDB遇上RISC-V | Mox的笔记库 SIGMOD25论文阅读:An Elephant Under The Microscope——Analyzing The Interaction Of Optimizer Components In PostgreSQL 论文阅读:Compile-Time Analysis of Compiler Frameworks for Query Compilation VLDB23阅读:Bringing Compiling Databases to RISC Architectures LingoDB源码编译与分析 | Mox的笔记库 淦!MLIR输出Hello World不应该这么难! | Mox的笔记库 如何愉快的运行一个MLIR程序 | Mox的笔记库 2024:拥挤年代的想象与创造 | Mox的笔记库 如何给自己的博客添加MLIR和LLVM IR语法高亮 | Mox的笔记库 VLDB19-Parsing Gigabytes of JSON per Second论文阅读 CIDR25:Runtime-Extensible Parsers阅读 | Mox的笔记库 MLIR学习资料整理 | Mox的笔记库 SIGMOD24文章阅读:VeriTxn | Mox的笔记库 VLDB23文章阅读——Exploiting Cloud Object Storage for High-Performance Analytics VLDB24——OLAP on Modern Chiplet-Based Processors走马观花阅读 VLDB22:YeSQL文章阅读(已废弃) | Mox的笔记库 如何让数据库中的Python跑的更快-VLDB22-YeSQL文章阅读 | Mox的笔记库 你好,世界! | Mox的笔记库 让系统研究更有意义:HarmonyOS NEXT的教训和经验——讲座回顾 | Mox的笔记库 UNSW 24T3 COMP9336上课记录 | Mox的笔记库 Velox开发环境配置踩坑记录 | Mox的笔记库 MLIR Toy Tutorial实践记录 | Mox的笔记库 论文阅读:Declarative Sub-Operators for Universal Data Processing LLVM-Kaleidoscope实操踩坑记录 | Mox的笔记库 2024年7月RSSHub开发体验 | Mox的笔记库 澳洲大学计算机硕士比较 | Mox的笔记库 论文阅读——CDUL:CLIP-Driven Unsupervised Learning for Multi-Label Image Classification 论批量快速添加图片与视频水印的事 | Mox的笔记库 CVPR2023-CLIP算法调研 | Mox的笔记库 基于元信息写入的服务器压力测试 | Mox的笔记库 MjAyMw==,希望,前进与平庸之道 | Mox的笔记库 家庭组网IPv6+Mesh折腾 | Mox的笔记库 code-server初体验 | Mox的笔记库 从Nginx到Caddy | Mox的笔记库 Hexo部署安装全流程回顾 | Mox的笔记库 RMM观察与初探 | Mox的笔记库 计算机网络课设——UDP/TCP/TLS Socket实验 | Mox的笔记库 JQuery的XSS初探 | Mox的笔记库 生产实习记录 | Mox的笔记库 Fedora-CoreOS配置与试用(2023年) | Mox的笔记库 Electron学习笔记 | Mox的笔记库 ServerSentEvent学习 | Mox的笔记库 报告翻译:容器云的安全挑战 | Mox的笔记库 Arch Linux迁移计划 | Mox的笔记库 Vagrant配置Metarget靶场环境 | Mox的笔记库 OpenAI-whisper折腾 | Mox的笔记库 202202,困惑,混乱与未曾设想之路 | Mox的笔记库 2022年Hack the box:Tier1免费区全解 | Mox的笔记库 Navidrome部署记录 | Mox的笔记库 长安杯2021-snake复现 | Mox的笔记库 报告概要翻译:OBFUSCATING C++ PROGRAMS VIA CONTROL FLOW FLATTENING 从零开始的Django CVE-2022-28346复现 | Mox的笔记库 2022CISCN(西北区赛)-The shinning | Mox的笔记库 Docker+QEMU+Arm64(Ubuntu)+环境配置(2022版) | Mox的笔记库 Arch Linux运行树莓派系统(2022年) | Mox的笔记库 2022CISCN初赛-ez_usb-复盘WriteUp | Mox的笔记库 NodeMCU-MicroPython配置实录 | Mox的笔记库 Django事务使用 | Mox的笔记库 记录第一次EduSRC上报 | Mox的笔记库 Jetbrain问题应急处理 | Mox的笔记库 Celery5.2学习&配置 | Mox的笔记库 Waline部署记录 | Mox的笔记库 2021年12月 Vivo千镜杯回顾 | Mox的笔记库 Frida hook初次实战 | Mox的笔记库 Log4j2漏洞复现 | Mox的笔记库
算法图解学习 | Mox的笔记库
2020-11-22 · via Mox的笔记库

作为算法学习的入门书,这本书棒极了

本书用的log均为2为底

很多文本直接参考了知乎专栏 https://zhuanlan.zhihu.com/p/38488791

GPS使用图算法来计算前往目的地的最短路径,在6,7,8章介绍

1.2 二分查找

首先,查找不是排序

折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列

对半开,比楞查效率更高

对数是幂运算的逆运算

大前提是先按大小排好序

def binary_search(list, item):

# low and high keep track of which part of the list you'll search in.

low = 0

high = len(list) - 1

# While you haven't narrowed it down to one element ...

while low <= high:

# ... check the middle element

mid = (low + high) // 2

guess = list[mid]

# Found the item.

if guess == item:

return mid

# The guess was too high.

if guess > item:

high = mid - 1

# The guess was too low.

else:

low = mid + 1

# Item doesn't exist

return None

my_list = [2, 3, 5, 7, 11,13]

print(binary_search(my_list, 13)) # => 1

# 返回所在位置

# 'None' means nil in Python. We use to indicate that the item wasn't found.

print(binary_search(my_list, -1)) # => None

1.3大O表示法

O 是 Operation 的简写

并非以秒为单位,基准值并不确定

例如,假设列表包含 n 个元素。简单查找需要检查每个元素,因此需要执行 n 次操作。使用大O表示法, 这个运行时间为O(n)

通过比较操作数,指出算法运行的增速

在二分查找中,最多需要检查log n个元素

时间复杂度:O(log2n)

1.3.3 大O表示法指出最糟情况下的运行时间

O(log n),对数时间

O(n),线性时间

O(n*log n),快速排序

O(n^2),选择排序,冒泡排序

O(n!),旅行商问题

大O表示法忽略1/2这样的常数

算法常常和数据结构挂钩。在介绍数据结构之前,我们需要先理解内存的工作原理,这样有助于我们理解数据结构。

2 选择排序

2.2 数组和链表

2.2.2 数组

要读取链表最后一个元素时,必须先从第一个元素开始读起

2.2.4 在中间插入

链表插入更简单,数组插入时要把后面的元素向后移

2.2.5 删除

链表修改地址即可

数组在删除元素后,将后面的元素向前移

数组支持随机访问

一种特殊的数据:链表数组

这个数组包含26个元素,每个元素指向一个链表

2.3 选择排序

运行时间O(n*1/2*n)

我觉得n(n+1)/2

# Finds the smallest value in an array

def findSmallest(arr):

# Stores the smallest value

smallest = arr[0]

# Stores the index of the smallest value

smallest_index = 0

for i in range(1, len(arr)):

if arr[i] < smallest:

smallest_index = i

smallest = arr[i]

return smallest_index

# Sort array

def selectionSort(arr):

newArr = []

for i in range(len(arr)):

# Finds the smallest element in the array and adds it to the new array

smallest = findSmallest(arr)

newArr.append(arr.pop(smallest))

return newArr

print(selectionSort([5, 3, 6, 2, 10]))

会有警告,i没有使用上,实际情况是i只用来循环

(C语言版本写的不好,原数列没有删掉,抽出的数用一个远大于数组的数取代,大O表示法应该是n的n次方)

3 递归

就是自己调用自己

“如果使用循环,程序性能可能更高;

如果使用递归,程序可能更容易理解”

3.2 基线条件和递归条件

递归条件:使函数调用自己的条件

基线条件:使函数不调用自己的条件

3.3 栈

后进先出,内存的一种储存方式

「栈」是一种先入后出(FILO)简单的数据结构。「调用栈」是计算机在内部使用的栈。当调用一个函数时,计算机会把函数调用所涉及到的所有变量都存在内存中。如果函数中继续调用函数,计算机会为第二个函数页分配内存并存在第一个函数上方。当第二个函数执行完时,会再回到第一个函数的内存处。

3.3.1 调用栈

所有函数调用都进入调用栈

写在函数里面的函数在最上层

调用一个另函数时,当前函数暂停并处在未完成的状态

这个栈用于存储多个函数的变量,被称为调用栈

3.3.2 递归调用栈

递归函数也使用调用栈,所以迭代过多会造成堆栈溢出

4 快速排序

4.1 分而治之

一种著名的递归式问题解决方案

第一,找出基线条件,这种条件尽可能简单

第二,不断将问题分解,直到符合基线条件

递归一定要记录状态吗??

4.2 快速排序

C语言标准库中的qsort实现的就是快速排序

基线条件为 空或只包含一个元素(因为不需要排序)

def quicksort(array):

if len(array) < 2:

# base case, arrays with 0 or 1 element are already "sorted"

return array

else:

# recursive case

pivot = array[0]

# sub-array of all the elements less than the pivot

less = [i for i in array[1:] if i <= pivot]

# 这是什么操作(python还有这种写法?)

# 从1开始,往后循环

# sub-array of all the elements greater than the pivot

greater = [i for i in array[1:] if i > pivot]

return quicksort(less) + [pivot] + quicksort(greater)

print(quicksort([10, 5, 2, 3, 8]))

找基准值——分区——缩小规模到两个或一个数

4.3 再谈大O排序法

选择排序的时间为O(n^2)

而合并排序的时间为O(n logn)

快速排序在最坏情况下时间为O(n^2)

平均情况为O(n logn)

4.3.1 比较合并排序与快速排序

大O表示法不考虑常量(单位运行时间)

实际上,快速查找遇上平均情况的可能性比最糟情况要高很多

因为除非每次调动都不移动(或大部分前面不移动),都属于平均情况

快速查找的常量比合并排序+二分查找要低

4.3.2 平均情况和最糟情况

快速排序最坏的情况是初始序列已经有序,第1趟排序经过n-1次比较后,将第1个元素仍然定在原来的位置上,并得到一个长度为n-1的子序列;第2趟排序经过n-2次比较后,将第2个元素确定在它原来的位置上,又得到一个长度为n-2的子序列;以此类推,最终总的比较次数: C(n) = (n-1) + (n-2) + … + 1 = n(n-1)/2 最坏的情况下,快速排序的时间复杂度为O(n^2)

所以,随机选择一个数作为基准值,一般都是平均时长

是分而治之的典范

5 散列表

最有用的数据结构之一

在编程语言中,存在另外一种和数组不同的复杂数据结构,比如JavaScript中的对象,或 Python 中的 字典。对应到计算机的存储上,它们可能可以对应为 散列表

哈希表又称散列表

5.1 散列函数

必须一一对应,且是确定关系

最理想的情况是,不同输入得到不同数字

散列表=散列函数+数组???

包含额外逻辑的数据结构??

数组和函数直接映射到内存,而散列表使用散列函数确定函数的储存位置

Python提供的散列表实现是字典(大括号)

book = {"apple": 0.67, "milk": 1.49, "avocado": 1.49}

book["Lisa"] = 100

print(book)

(而C没有提供实例)

散列表将键映射到值

5.2 应用案例

5.2.1 将散列表用于查找

散列表是提供DNS解析的一种方式

5.2.2 防止重复

散列表与列表的最大差别在于:列表需要遍历才能查询,而散列表不需要(很明显散列表占用的资源更多)

voted = {}

def check_voter(name):

if voted.get(name):

print("kick them out!")

else:

voted[name] = True

print("let them vote!")

check_voter("tom")

check_voter("mike")

check_voter("mike")

5.2.3 将散列表用作缓存

5.3 冲突

即一对一映射中,另外一边映射的是链表

最理想的情况是:

散列函数将键均匀映射到散列表的不同位置

5.4 性能

如何选择一个好的散列函数?

数列表的平均运行为常量时间(简单查找是线性时间,二分查找是对数时间)

最糟情况是O(n) (为什么?目前没有找到原因?)

5.4.1 填装因子

填装因子=散列表包含的元素数/位置总数

填装因子越低,发生冲突的可能性越低,散列表性能越好

填装因子超过0.7就建议调整长度

良好的散列函数让数组中的值呈均匀分布,不过我们不用担心该如何才能构造好的散列函数,著名的SHA 函数,就可用作散列函数

6 广度优先搜索

数据结构图创建网络模型

拓扑排序,指出节点的依赖关系

6.1 图简介

将现实描绘成点线图

解决最短路径的算法被称为广度优先搜索

6.2 图是什么

图由节点(node)和边(edge)组成,它模拟一组连接。一个节点可能与众多节点直接相连,这些节点被称为邻居。有向图指的是节点之间单向连接,无向图指的是节点直接双向连接。

图用于仿真不同的东西是如何相连的

在编程语言中,我们可以用散列表来抽象表示图

6.3 广度优先搜索

广度优先搜索可解答两类问题:

第一,两个节点间存不存在路径

第二,两个节点间哪条路径最短

6.3.2 队列

即堆栈中的堆(先进先出)(FIFO)

队列的工作原理和现实生活中的队列完全相同,可类比为在公交车前排队,队列只支持两种操作:入队 和 出队。 队列是一种先进先出的(FIFO)数据结构。

FIFO=First In First Out

6.4 实现图

通过散列表实现,用表来实现图

散列表模拟图 散列表是一种用来模拟图的数据结构(???)

6.5 实现算法

from collections import deque

def person_is_seller(name):

return name[-1] == 'm'

graph = {}

graph["you"] = ["alice", "bob", "claire"]

graph["bob"] = ["anuj", "peggy"]

graph["alice"] = ["peggy"]

graph["claire"] = ["thom", "jonny"]

graph["anuj"] = []

graph["peggy"] = []

graph["thom"] = []

graph["jonny"] = []

def search(name):

search_queue = deque() #定义其为队列

search_queue += graph[name]

# This array is how you keep track of which people you've searched before.

searched = []

while search_queue:

person = search_queue.popleft()

# Only search this person if you haven't already searched them.

if person not in searched:

if person_is_seller(person):

print(person + " is a mango seller!")

return True

else:

search_queue += graph[person]

# Marks this person as searched

searched.append(person)

return False

search("you")

全局变量定义时,无视顺序

但字典里的键是唯一的,理论上是不会重复的

如果一个人为同一级两个人的好友,则需要一个表记录下已经登记过人,否则就会导致无限循环

运行时间至少是O(边数)

再算上队列检查时间O(人数)

所以广度优先搜索的运行时间为O(边数+人数)

如果任务A依赖任务B,在列表中任务A就必须在任务B后面

这被称为拓扑排序

只能往下指的图,被称作树

7 狄克斯特拉算法

引入加权图

环会使狄克斯特拉算法失效??

最短路径不一定是最快路径,广度优先只能解决最短路径,而狄克斯特拉算法则可以解决这个问题,找出总权重最小的路径

找到图中最便宜的节点,并确保没有到该节点更便宜的路径

7.1 使用狄克斯特拉算法

第一,找出最短时间内能前往的节点,终点时间先设为无限

第二,对于该节点的邻居,检查是否有前往他们的更短路径,如果有则更新开销

第三,重复这一过程

第四,计算最终路径

我认为关键是对所有路径使用该算法

7.2 术语

狄克斯特拉算法只适用于有向无环图

其实应该是正权重有环图,环会因为权重被抛弃??

7.3 换钢琴

7.4 负权边

负权边不能使用狄克斯特拉算法

因为狄克斯特拉算法有这样的假设:

对于处理过的节点,没有前往该节点的更新路径

7.5 实现

# the graph

# 用于确定父连接

graph = {}

graph["start"] = {}

graph["start"]["a"] = 6

graph["start"]["b"] = 2

graph["a"] = {}

graph["a"]["fin"] = 1

graph["b"] = {}

graph["b"]["a"] = 3

graph["b"]["fin"] = 5

graph["fin"] = {}

# the costs table

# 用于初始化

infinity = float("inf")

costs = {}

costs["a"] = 6

costs["b"] = 2

costs["fin"] = infinity

# the parents table

parents = {}

parents["a"] = "start"

parents["b"] = "start"

parents["fin"] = None

processed = []

def find_lowest_cost_node(costs):

lowest_cost = float("inf") #函数初始化

lowest_cost_node = None

# Go through each node.

for node in costs:

cost = costs[node]

# If it's the lowest cost so far and hasn't been processed yet...

if cost < lowest_cost and node not in processed:

# ... set it as the new lowest-cost node.

lowest_cost = cost

lowest_cost_node = node

return lowest_cost_node

# Find the lowest-cost node that you haven't processed yet.

node = find_lowest_cost_node(costs)

# If you've processed all the nodes, this while loop is done.

while node is not None:

cost = costs[node]

# Go through all the neighbors of this node.

neighbors = graph[node]

for n in neighbors.keys():

new_cost = cost + neighbors[n]

# If it's cheaper to get to this neighbor by going through this node...

if costs[n] > new_cost:

# ... update the cost for this node.

costs[n] = new_cost

# This node becomes the new parent for this neighbor.

parents[n] = node

# Mark the node as processed.

processed.append(node)

# Find the next node to process, and loop.

node = find_lowest_cost_node(costs)

print("Cost from the start to each node:")

print(costs)

首先,需要3个散列表

第一个表储存节点的邻居

第二个表储存每个节点的开销

开销指的是从起点出发前往该节点所需要的时间

由于不知道终点要多久,先设为无穷大

python中的inf为无穷大

如果图中包含负权边

7.6 小结

如果图中包含负权边,使用贝尔曼-福德算法

8 贪婪算法

寻找近似解,处理没有快速算法得问题

8.1 教室调度问题

贪婪算法即是每步都采用最优解

8.2 背包问题

贪婪算法不一定是最优解,但应当与最优解相近

8.3 集合覆盖问题

# You pass an array in, and it gets converted to a set.

states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"])

stations = {}

stations["kone"] = set(["id", "nv", "ut"])

stations["ktwo"] = set(["wa", "id", "mt"])

stations["kthree"] = set(["or", "nv", "ca"])

stations["kfour"] = set(["nv", "ut"])

stations["kfive"] = set(["ca", "az"])

final_stations = set()

# 第一遍时ktwo因为长度与kone的范围一样而没被纳入

while states_needed: #在遍历中,直到states_needed全部清空

best_station = None

states_covered = set()

for station, states_for_station in stations.items(): ##没看懂

covered = states_needed & states_for_station ## 取交集

if len(covered) > len(states_covered):

best_station = station

states_covered = covered

states_needed -= states_covered

final_stations.add(best_station)

print(final_stations)

近似算法

贪婪算法即是一种近似算法

准备工作-计算答案-集合处理

其判断优劣的方法是:

1.速度有多快

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

完美是优秀的敌人。有时候,你只需要找一个能够大致解决问题的算法,此时贪婪算法正好可派上用场,它们的实现很容易,得到的结果又与正确结果接近。这时候采用的算法又被称作近似算法。

快速排序应该是近似算法????

8.4 NP完全问题

如何识别NP完全问题

以下是NP完成问题的一些特点,可以帮我我们识别NP完全问题:

  1. 元素较少时,算法的运行速度非常快,但是随着元素的增加,速度会变得非常慢;
  2. 涉及 所有组合 的问题通常是NP完成问题;
  3. 不能将问题分解为小问题,必须考虑各种可能的情况的问题,可能是NP完全问题;
  4. 如果问题涉及到序列且难以解决(旅行商问题中的城市序列),则可能是NP完全问题;
  5. 如果问题涉及到集合(如广播台集合)且难以解决,可能是NP完全问题;
  6. 如果问题可转换我集合覆盖问题或者旅行商问题,一定就是NP完全问题;

9 动态规划

大事化小,小事化无

还有一种被称作「动态规划」的思维方式可以帮我们解决问题 这种思维方式的核心在于,先解决子问题,再逐步解决大问题。这也导致「动态规划」思想适用于子问题都是离散的,即不依赖其他子问题的问题。

动态规划使用小贴士:

  • 每种动态规划解决方案都设计网格;
  • 单元格中的值通常是要优化的值;
  • 每个单元格都是一个子问题

附:什么是动态规划?动态规划的意义是什么?—知乎讨论

这个解答很棒!

动态规划只能拿和不拿整件商品,无法考虑拿走商品的一部分

可用于模糊搜索的寻找最长公共子串

10 K最邻近算法

余弦相似度?? 取代 最近距离

本书对 KNN 也做了简单的介绍,KNN的合并观点如下

  • KNN 用于分类和回归,需要考虑最近的邻居。
  • 分类就是编组
  • 回归就是预测结果
  • 特征抽离意味着将物品转换为一系列可比较的数字。
  • 能否挑选合适的特征事关KNN算法的成败

11 进一步的学习建议

读完本书,对算法总算有了一个入门的理解,当然算法还有很多值得深入学习的地方,以下是作者推荐的一些方向。

  • 反向索引:搜索引擎的原理
  • 傅里叶变换:傅里叶变换非常适合用于处理信号,可使用它来压缩音乐;
  • 并行算法:速度提升并非线性的,并行性管理开销,负载均衡
  • MapReduce:是一种流行的分布式算法,可通过流行的开源工具 Apache Hadoop 来使用;
  • 布隆过滤器和 HyperLogLog:面对海量数据,找到键对于的值是一个挑战性的事情,布隆过滤器是一种概率性的数据结构,答案可能不对也可能是正确的;其优点在于占用的存储空间很小
  • SHA 算法(secure hash algorithm)安全散列函数,可用于对比文件,检查密码
  • 局部敏感的散列算法,让攻击者无法通过比较散列值是否类似来破解密码
  • Diffie-Hellman 密钥交换
  • 线性规划:用于在给定约束条件下最大限度的改善制定的指标

Diffie-Hellman 密钥交换

其继任者为RSA,简单易懂的公钥,私钥加密方案