比较常规的想法是,维护一个集合Set来记录我们构造什么样的面值。我们按照从小到大的顺序挨个考察coins,对于当前的c,能够带来什么样的新面值呢?显然就是Set里面的每个元素(包括空元素)分别加上c。
我们这个时候再看一下这个Set,如果此时集合里下一个待构造的面值next小于c的话,那么这个面值以后肯定就再也无法构造。因为之后我们遇到的单个硬币都会比next更大,不会带来任何帮助。
这个解法中,集合需要存储可以构造的所有面值,这个数量可能会非常大。比如说k个硬币,任意组合的面值都不重合的话,那么就会有2^k种面值。当考察第k+1个硬币带来的集合更新时,很可能会TLE。
本题的突破口其实是,要注意到,每次这个集合的元素其实都应该是保证连续的!
假设当前集合能够构造从0到curMax的连续面值。那么显然加入新硬币c之后,就能够构造从c到curMax+c的连续面值。如果[0,curMax]和[c,curMax+c]这两段区间是交叠的,那么新的curMax就是curMax+c。如果这两段区间不交叠,即curmax+1 < c
(注意+1),那么说明curMax+1无法构造。注意,此后的新硬币面值都将大于c,那么也意味着大于curMax+1
。说明以后任何新硬币都不会给构造curMax+1带来帮助。此时能构造的连续面值就是[0, curMax].