闲来无事,想做个小项目玩玩,也可以趁此机会亲身体验开发的每一个环节。第一步就是搭建环境:一个应用服务器,用于部署后台代码。
环境概览
- 云服务:阿里云ECS,1核/2G/40G/1Mbps带宽
- 操作系统:CentOS7.8 64位
- MySQL 5.6
- Nginx 1.18
- Tomcat 8.5
动态规划(Dynamic Programming, DP)与其说是一种算法,更准确地说是一种解决问题的思维方式,因为其并没有对所有相关问题抽象出一种通用的算法程序,而是要在解题时根据具体的问题运用动态规划的思想进行问题的建模并编码求解。因此在理解动态规划解题之前,首先要了解什么样的问题能够用动态规划的思想解决。
本质上来说,动态规划是一种更高效的递归算法的实现,所以在学习动态规划之前要对递归算法有比较深刻的理解。
在用朴素递归解决问题时,首先将目标问题分解成多个子问题,而在解决这些子问题时又被分解成更小的子问题……如此重复,直到分解到递归的边界为止。在分解过程中,同一个子问题可能会被多次重复解决。
动态规划的思想就是,每解决一个子问题,都将该子问题的结果保存起来,则每个子问题只需要被解决一次。那么,哪些递归算法可以用动态规划的思想去实现呢?最简单的方法就是看朴素递归的算法有没有将同一个子问题一次次重复计算(可以画一个简单的递归树,能够很直观地发现,如果同一个子问题在树中不断出现,并且不止一次地出现在非叶节点上,那么就可以判断该子问题被重复计算了)。
对于一类问题,问题的输入是一些对象两两之间的“相连关系”,并且这种“相连关系”是一种等价关系,即它具有以下性质:
那么我们可以把相连的对象划分为一个等价类。问题的目标是根据输入的所有相连关系,将对象空间划分为多个等价类,并能够判断任意两个对象是否属于同一个等价类。这个问题称为动态连通性问题,动态连通性问题有以下现实场景的应用:
在前一篇文章Spring探秘2:ApplicationContext启动流程中提到了Spring容器启动的最后一步是refresh,即配置的刷新,这是容器启动过程中一个核心的步骤,实现了启动容器的主要的功能。本文会简单介绍一下AbstractApplicationContext#refresh()方法的流程,其中涉及到的比较复杂的过程还需要另外详细分析。首先其源码如下:
ApplicationContext是Spring框架中最基础的接口之一,可以认为其实现类就是一个Spring的环境(容器),而一个简单的Spring应用的启动过程就是一个ApplicationContext的实现类的实例化过程,是研究Spring源码的很好的切入点。这里研究的实现类是AnnotationConfigApplicationContext,运行的代码为前文Spring探秘0:源码构建中的测试代码,启动类的代码如下:1
2
3
4
5
6
7
8
9
10public class DemoApp {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
DemoComponent component = context.getBean(DemoComponent.class);
component.foo();
}
}