定义k为一个区间的长度。
则上述公式可以写作dp(i,i+k) = max(values[i] + sum(i+1,i+k) - dp(i+1,i+k) , values[i+k] + sum(i,i+k-1) - dp(i,i+k-1))
现在将dp的第二维定义为这个区间的长度,所以dp(i,k)的含义变成了区间(i,i+k)先手玩家可以取到的最大硬币总价值。
上述公式变为dp(i,k) = max(values[i] + sum(i+1,i+k) - dp(i+1,k-1) , values[i+k] + sum(i,i+k-1) - dp(i,k-1))
由上述的公式可以很容易的写出代码了,时间复杂度O(N^2),空间复杂度O(N^2)
其实空间复杂度还是可以优化的,第一种方法:可以滚动数组,可以把空间复杂度变为O(N)。第二种方法:与背包算法的空间优化类似,将i变成从后向前找,空间复杂度为O(N),这个比前面一种优化方法,常数小一些。
公式变为 dp1(i) = max(values[i] + sum(i+1,i+k) - dp1(i+1) , values[i+k] + sum(i,i+k-1) - dp1(i)) i 从后向前遍历
这里有一个问题,dp1(i+1)这个值在计算dp1(i+1)的时候被改变了,但是在计算dp1(i)之中又用到了,所以在改变之前需要存储这个值。
时间复杂度O(N^2),空间复杂度O(N)。代码如下: