数据结构与算法

Tags: 系统设计 

目录

给元素以及角色,使其相互关联, 树是各种关联方式中的一种.

完全二叉树

每一个父节点都有两个孩子, 只有树的最后一层可能是不满的.

假如按照从根节点开始, 编号从1开始, 每一层从左到右的顺序给结点编号, 父子之间的编号有规律可循.

父节点编号 = i
左孩子编号 = 2*i
右孩子编号 = 2*i + 1

因此, 可以把完全二叉树塞到一个数组中, 或者说数组本身就是一个完全二叉树, 只是以前不知道而已

完全二叉树的实现开销是最小的, 不需要额外使用指针定位.

寻找最优解

动态规划

有一类寻找最优的问题可以用动态规划的方法解决.

按照《算法导论》中的正式说法, 这类问题要具有下面的两个特点, 才可以使用动态规划的算法:

1  最优子结构
2  重复子问题

动态规划本质上是一种自底向上的穷举方法, 先把最底层的子问题的答案准备好, 一层层的向上计算, 直到最后一层.

只适合具有最优子结构的问题, 并且要有重复的子问题, 才能显示出动态规划的优势.

按照我自己的理解, 这类问题可以通过三步进行(以矩阵链乘法问题为例):

矩阵链乘法问题:

	表达式: A1*A2*A3*A4*...An  A是矩阵

	怎样通过加括号的方式改变运算次序, 使整个表达式的计算过程中乘法运算的次数最少?
  • 第一步, 如果用穷举的方式, 怎么解决?

考虑用穷举的方式如何解决, 并不是真的要靠穷举的方式获得结果, 真正的目的是弄清楚问题是什么, 将文字性的描述具象化, 在脑海中构建起整个场景.

要给表达式加括号, 括号里面又可以包含括号, 直观感觉括号里嵌套括号的情况不好穷举. 可以首先只穷举括号不包含的情况, 加完第一层括号后, 计算出新的缩短后的表达式, 再对这个表达式穷举括号不包含的情况, 直到最后只剩下了两个矩阵.

例如, 下面是第一层括号的一种添加方法:

A1*A2*(A3*A4)...An [式1]  --> A1*A2*A34*...An  [式2]

然后用同样的方法对[式2]加括号.

而且在添加括号的时候, 不需要考虑括号内有两个以上矩阵的情况

例如:

A1*A2*(A3*A4*A5)...An  等同于  A1*A2*(A3*A4)*A5 --> A1*A2*(A34*A5)

这里的等同指的是, 乘法运算的次数是相同的.

因此, 每次加括号的时候, 就可以依次考虑加一个括号有几种加法、加两个括号有几种加法, 直到完成穷举.

  • 第二步, 问题是否可以划分成子问题, 用递归的方式解决?

递归只是实现手段, 实际是在考虑问题是否可以不断的被分割到最简单的情形. 也就是具有最优子结构.

在脑海中模拟一下表达式的运算过程, 首先最内层的括号内的矩阵相乘, 然后次内层的括号的矩阵, 依次进行, 直到最外层的完成后, 剩下了两个矩阵.

留心, 最后一步的时候就剩下了两个矩阵, 一个乘号. 这说明什么呢? 最后剩下的那个乘号把原先的表达式一分为二了.

那么乘法运算次数最少的加括号方式中, 最后剩下的是哪一个乘号呢? 不清楚, 但是可以试:

如果是第1个乘号,  那么算出用了M1次乘法
如果是第2个乘号,  那么算出用了M2次乘法
...
如果是第n个乘号,  那么算出用了Mn次乘法

M1..Mn中那个值最小, 最后剩下的就是哪个乘号, 这个乘号的两边需要使用括号括起来的表达式.

关键是, 当我们选定一个乘号后发现, 这个乘号两边不是出来了两个相同的问题了吗? 果断判定可以直接上递归.

  • 第三步, 在用递归的方式解决的过程中, 是否总是遇到重复的问题?

在递归的过程中发现有些子问题被重复计算了.

例如:

假定1:
	(A1 A2 A3 A4) * (A5 A6 A7 A8)  --> (A1 (A2 A3 A4)) * (A5 A6 A7 A8)

假定2:
	A1 * (A2 A3 A4 A5 A6 A7 A8) --> A1 * ((A2 A3 A4) * (A5 A6 A7 A8))

在两次假定中,都遇到了子问题(A2 A3 A4)和(A5 A6 A7 A8), 也就是说这两个子问题在这两次假定中被计算了两遍. 果断判定可以使用动态规划.

  • 动态规划解法

在使用递归的方法的时候, 遇到子问题被重复计算的情形, 影响了算法效率. 那么可不可以事先把所有的子问题都计算出来, 直接把结果用于更上一层的问题?

既然递归实际上也是在穷举, 那么也就是说用事先计算所有子问题的方式遇到的子问题的种类和用递归的方式遇到的子问题的种类是相同, 不存在做了无用计算的情况.

首先考虑最底层的子问题有哪些? 递归的最后一层就是只有两个矩阵的情况, 所以把两个矩阵直接加括号的次数全部计算出.也就是:

A1*A2
A2*A3
A3*A4
A4*A5
...
An-1*An

再上一层的子问题:

A1*A2*A3   --> 用到子问题A1*A2  A2*A3
A2*A3*A4   --> 用到子问题A2*A3  A3*A4
A4*A5*A6   --> 用到子问题A4*A5  A5*A6

直到:

A1*A2*A3...An

对于矩阵链乘法, 可以用一个二维数组记录子问题的答案

	1 2 3 4 5 6
1   0
2     0
3       0
4         0
5           0
6             0

资料:

《算法导论》第二版, 15章, 动态规划.

系统设计

  1. Netflix 的异地多活设计: Active-Active for Multi-Regional Resiliency
  2. Facebook 的缓存系统实践经验《Scaling Memcache at Facebook》
  3. 多机数据系统的正确性与一致性
  4. 《大型网站技术架构: 核心原理与案例分析》阅读摘录
  5. 《分布式金融架构课》阅读笔记2: 线性一致的分布式数据系统的实现过程
  6. 《分布式金融架构课》阅读笔记1: 单机&多机并发/多副本读写正确性和一致性
  7. 《消息队列高手课》阅读笔记: Rabbit/Rocket/Kafka/模型/消息事务/保序等
  8. 《消息队列高手课》阅读笔记: Rabbit/Rocket/Kafka/模型/消息事务/保序等
  9. 《Redis核心技术与实践》阅读笔记: 数据类型/存储开销/Rehash/案例等
  10. 《Redis核心技术与实践》阅读笔记: 数据类型/存储开销/Rehash/案例等
  11. 《高并发系统设计40问》阅读笔记: 数据库/缓存/消息队列/分布式服务
  12. 《高并发系统设计40问》阅读笔记: 数据库/缓存/消息队列/分布式服务
  13. 《MySQL实战45讲》阅读笔记: 索引类型/数据可靠性/事务/间隙锁/临时表等
  14. 系统性能分析方法论: 统计图谱工具
  15. 张磊《深入剖析Kubernetes》专栏的阅读笔记
  16. 代理服务软件haproxy、nginx、envoy对比,以及开源的API网关项目对比
  17. 蓝绿部署、金丝雀发布(灰度发布)、A/B测试的准确定义
  18. 阿里巴巴的应用限流和服务降级是怎样实现的?|如何打造平台稳定能力
  19. 陈皓《左耳听风》专栏的阅读笔记(持续更新)
  20. 好雨云帮,一款不错的国产开源PaaS
  21. 怎样为软件的不同版本命名?
  22. 怎样选择开源项目的license?
  23. Glusterfs的架构
  24. 怎样设计一个企业级的PaaS平台?
  25. 几种常见的LDAP系统
  26. DNS SRV介绍(一种用DNS做服务发现的方法)
  27. DNS,DNS-Domain Name System
  28. 思科的网络设备
  29. 虚拟化技术汇总
  30. 认证与授权系统的汇总
  31. 高可用实现方法汇总
  32. 编译器汇总
  33. Linux系统的优化方法
  34. CentOS7的一些变化
  35. 分布式系统的一些知识
  36. 计算机编程语言的特性汇总
  37. 网络通信的一些基础知识
  38. PCIE总线的一些知识
  39. 操作系统的API
  40. 网卡的一些知识
  41. Linux系统的构建过程
  42. 数据结构与算法
  43. CPU的相关知识

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球