前言
算法与数据结构是计算机科学中的核心内容,算法是研究解决问题的方法,而数据结构则是设计一种更好的组织和使用数据的方式。
算法与数据结构的核心是处理计算机问题的一些基本原则和经典案例。通常我们要修改已有算法,或者创造算法,才能解决实际问题,活学活用才真正掌握。
其实用计算机解决一个问题就是在思考如何将这个问题表达成状态(用哪些变量存储哪些数据)数据结构 以及如何在状态中转移(怎样根据一些变量计算出另一些变量)算法。
空间复杂度就是为了支持你的计算所必需存储的状态最多有多少,时间复杂度就是从初始状态到达最终状态中间需要多少步!
另外介绍下状态与阶段的概念,用于区分不同的算法其特点。
到达最终阶段的过程可能有不同的阶段,每个阶段都可能有多个状态。
一个阶段的一个状态可以得到下个阶段的所有状态中的几个。我们要计算出最终阶段的状态数要经历之前每个阶段的某些状态。
数学归纳法
Mathematical Inducation, 常用于证明对某个对象的描述在自然数范围内成立。
若要证明某个命题对于自然数n都成立,则
- 证明命题对于n=1成立。
- 假设命题对于n成立,n为任意自然数,证明在此假设下,命题对于n+1成立。
类似多米诺骨牌
递归
Recursion,指计算机程序调用其自身,为了保证计算机不陷入死循环,需要有一个终止条件,base case.
递归其实是一种数学归纳法,是一种计算方法。
例如,计算斐波那契数列。每个阶段由上一阶段的唯一结果推导。
数据结构中栈的实现应用了递归的思想。
贪心
Greedy algorithm,下一步的最优是从当前最优得到的,为了计算最终的最优值,只需要存储每一步的最优值即可。
例如,寻找从棋盘左上角到右下角最短需要几步。
动态规划
Dynamic Programming
dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems.
第i个阶段的最优解只由前i-1个阶段的最优解得到。即每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到-最优子结构,而不用关心之前这个状态是如何得到的-无后效性。通过状态的合并减少计算量
例如LIS问题,最长上升子序列,关键在于如何拆分问题,定义状态,发现问题状态与之前状态转移的关系。
此外,实际中有的问题往往需要对每个阶段的所有状态都算出一个最优值,然后根据这些最优值再来找最优状态。如背包问题
搜索
暴力求解,需要保存的是之前每个阶段所经历的那些状态,根据这些信息才能计算出下一个状态,即便当前阶段的状态不变,之前的阶段不同的状态会影响之后的结果。
小结
算法 | 适用于 |
---|---|
递归 | 每个阶段只有一个状态 |
贪心 | 每个阶段的最优状态都是由上一个阶段的最优状态得到 |
动态规划 | 每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到而不管之前这个状态是如何得到的 |
搜索 | 每个阶段的最优状态是由之前所有阶段的状态的组合得到的 |
选取用什么算法,是由这个问题本身阶段间状态的转移方式决定的,即状态表示的空间,而贪心,动态等均与递归有关。