刷题总结

状态机

计算机的本质是一个状态机,内存里存储的所有数据构成了当前的状态,CPU只能利用当前的状态计算出下一个状态。

你企图使用计算机解决一个问题是,其实就是在思考如何将这个问题表达成状态(用哪些变量存储哪些数据)以及如何在状态中转移(怎样根据一些变量计算出另一些变量)。所以所谓的空间复杂度就是为了支持你的计算所必需存储的状态最多有多少,所谓时间复杂度就是从初始状态到达最终状态中间需要多少步!

状态转移衔接两个不同的阶段,不同的阶段通过转换来实现。

关心输入

输入提供了问题的规模和原始数据,也就是问题的状态表达,很多时候,要对输入做必要的限制和约束,处理极端情况。

问题规模思考

问题规模越大,程序就越复杂。编程很重要的一点就是要不断缩小问题规模。这也是指导动态规划,分治法,贪心等算法思想的核心思想。

信息的充分利用

在解决问题的过程中,会有很多信息产生,要充分利用已经产生的信息来减少对未产生信息的计算。典型的算法思想:回溯法&&分支限界法。二者本质上都是一致的,都是充分利用已经计算过的信息,来实现对树的剪枝。回溯法利用回溯过的线路中的最优值对树的其他线路进行剪枝;分支限界法则是充分利用遍历过的树的上层信息来实现对树的下层信息的剪枝。

深搜和广搜

绝大多数问题都能通过bfs,dfs解决。因为二者的本质是遍历解空间。

要把握状态的概念,也就是不同的节点在程序不同的时期有着不同的状态,对于某些具有特定状态并且程序执行的后面要用到的节点,将之放入特定容器。

在图搜索中,节点的状态有很多种(节点的状态此时主要根据操作来定义),比如:未被访问的节点,被访问但是后续仍要用于寻找相邻节点的点,被访问并且后续不会被用到的点。其中,第二类点仍要使用的必要,因此将之放入特定容器,也就是队列或者栈。

注意,深搜是通过使用栈来保证实现回溯的:也就是最先访问的点,最后处理其邻接关系。
广搜是通过使用队列来保证实现回溯的:也就是最先访问的点,最先处理其邻接关系。

动态规划

动态规划是一种算法设计技巧。动态规划的本质是通过建立dp数组,记录历史数据,来避免重复计算,以提高效率。递归的自上而下的暴力解法–>带备忘录的递归解法–>非递归的自下而上的动态规划解法。

递归思想

关于递归,递归的基本思想是某个函数直接或者间接地调用自身,这样就把原问题的求解转换成许多性质相同但是规模更小的子问题。

我们只需要关注如何把原问题划分成符合条件的子问题,而不用去研究这个子问题是如何被解决的。

递归代码最重要的两个特征:结束条件和自我调用。

明白一个函数的作用并相信他能完成这个任务,千万不要试图从细节上分析递归代码,否则很容易陷入无穷的细节中搞得疲惫不堪,人脑能压几个栈啊?

还是那句话,明白每个递归函数能做的事,并相信他们能够完成。

程序 = 数据结构 + 算法

这个公式不只是用来说明二者的重要性的,其本质如下:

数据结构 + 算法 + 编程思想

基本存在 + 相互作用 + 演化逻辑

数据结构保存信息,算法处理信息,数据结构保存状态,算法用于状态转化

数据结构的状态决定算法,算法改变数据结构的状态,二者的关系是相互影响,相互依赖。

数据结构体现的是内存的分配,而算法体现的是cpu的使用策略。

数据结构可能有的特质有:有序;独特;检索(key&&value)

理解查找

查找是增删改查的基础,而查找的前提是要在数据结构中建立键值对之间的映射关系,查找的过程是利用键和值之间的相互映射,完成查找。

算法思想

每个阶段只有一个状态->递推;

每个阶段的最优状态都是由上一个阶段的最优状态得到的->贪心;

每个阶段的最优状态是由之前所有阶段的状态的组合得到的->搜索;

每个阶段的最优状态可以从之前某个阶段的某个或某些状态直接得到而不管之前这个状态是如何得到的->动态规划。