先来看一个例题
整个数组A的和我们是能求出来的,由于我们需要分成两个和相等的子数组,那么两个子数组的和我们也能算出来。题目可以转换成:
我们使用数组B={b1,b2,b3,…,},里面每个元素的取值范围是0或者1,表示A{i}是否被选择,1表示选择,0表示未被选择,这样我们就可以用一个数学式子来表示
从数学上来说,这一类问题为了达到某一个目标(函数值最小,函数值最大,或者函数值等于某个值),我们需要确定n个变量的值,这一个过程叫规划
常见的规划问题有,线性规划,整数规划,01规划等等,那些神经网络本质上也属于规划问题
动态规划首先是个整数规划。整数规划是np完全问题,动态规划就是利用一些特殊的限定条件,使得将问题转换成多项式复杂度。
也就是说,动态规划描述了一种解决特殊规划问题的办法。动态,顾名思义,就是增量计算。假设我们已经规划好n个变量,如果再加上一个变量,我们不再需要重新规划前面那n个变量,只需要规划这第n+1个变量,这种方式叫动态规划
动态规划有三个条件
第三个条件是关键,如果没有这个条件,那么搜索空间并没有变化,使用动态规划跟不使用动态规划没有性能上的提升,也就没有意义了
前面那个例子,如果不用动态规划的思想,我们需要枚举所有的B数组的可能性,也就是2^n种可能性
由于题目限定数据范围,数组长度不超过200,数组元素不超过100,那么说明元素和不超过20000。我们引入中间状态C={C0,C1,…C10000},每个元素为0或1,第i个元素表示前面p个元素是否有存在和为i的子集。那么我们把状态空间降到了最高10000个,每次加入一个元素,只需要更新这最高10000个状态即可
假设这个题目没有限定数据范围。数组元素可以任意大,那么我们的中间状态空间最高可达2^n种可能,那么我们也没必要使用这种方式来解题
为什么2^n种可能性会降到只剩下10000种可能呢?因为中间有很多可能性产生的状态一致,比如集合{1,2,3,4,5}中,{2,3,4}和{1,3,5}产生的状态都是9,这些状态既然一致,并且如何得出这些状态是无关紧要的,因为如果这个集合再加入一个数,我们只需要拿状态值为9来计算得到下一个状态即可,并不需要理会是从{2,3,4}还是{1,3,5}得到的状态值,这种就大量的压缩了搜索状态空间。
这里表示两种情况,加入第k个数,跟不加入第k个数
1 | class Solution { |