Algorithm:每周至少做一个 leetcode 的算法题
该题目是一道非常经典的动态规划算法题,一种完全背包的解法,每一种零钱能凑出来的金额的方式数,都从小金额一直统计到大金额,例:要凑5块钱,有1、2、5块三种零钱,那么可以创建一个大小为比5块数值大1的数组,即new int[amount+1],然后统计1块至5块,每一个金额,1块钱零钱能凑出来的方式数量,得到的结果为[1,1,1,1,1,1](第一个元素默认为1,因为要凑得金额如果为0,则肯定也只有一种方式,也就是什么零钱都不用),然后第二步是统计2块钱零钱能凑出来的方式数量,循环至索引为2的时候,也就是统计金额2的凑成方式数,那么数量则为原有1块钱凑成金额2的1种方式 加上 当前2块钱凑成的1种方式 等于2种方式,这时候结果是[1,1,2,1,1,1],然后循环至3的时候,也就是统计金额3的凑成方式数,那么数量则为原有1块钱凑成金额3的1种方式 加上 金额1凑成的方式数量(因为3-2之后得到的1,也就是说1有多少种凑成方式,那么相应的3就有多少种(和零钱2凑成金额3)的方式),这时候结果是[1,1,2,2,1,1],周而复始,到4的时候结果是[1,1,2,2,3,1],到5的时候结果是[1,1,2,2,3,3],然后统计下一个零钱5块的时候,得到的结果就是[1,1,2,2,3,4]
1 | public int change(int amount, int[] coins) { |
1 | TreeNode pre = null; |
Review:阅读并点评至少一篇英文技术文章
Tip:学习至少一个技术技巧
java的SPI机制
java的spi机制,是开发人员通过在jar包的META-INF/services目录底下,创建一个class全路径相同名称(不包含.class)的文件,例1
META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
并在文件内以行为单位,每个单位为一个class的全路径(不包含.class),例1
2com.alibaba.csp.sentinel.transport.init.CommandCenterInitFunc
com.alibaba.csp.sentinel.transport.init.HeartbeatSenderInitFunc
然后使用ServiceLoader的load方法,就能通过把services目录下,与InitFunc接口的全路径名称1
com.alibaba.csp.sentinel.init.InitFunc
相同名称的文件内,实现了InitFunc接口的所有类都实例化并加载为loader实例(可遍历的集合)1
2
3
4ServiceLoader<InitFunc> loader = ServiceLoader.load(InitFunc.class);
for (InitFunc initFunc : loader) {
}
很多人看到这里,会想,这样做有什么意义呢?的确,我这里还没说完,到重点了。
当我们的代码是一个通讯服务,分为了三个jar包,A为核心core,实现了具体的通讯信息处理逻辑,而B和C是负责通讯的实现,其中B为Netty实现,C为简单的SocketServer实现,当我们只引入B或者C的其中一个Jar,而A在调用1
ServiceLoader.load(InitFunc.class)
后,会去加载B或者C的jar下1
META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
文件内的InitFunc实现类实例化,如果引入的是B,那么我们的通讯服务就会以Netty实现,反之则是SocketServer,这样,我们就能利用spi机制,通过引入的jar包而选择具体的实现方式。