从数列A[0], A[1], A[2], …, A[N-1]中选若干个数,要求对于每个i(0<=i< N-1),A[i]和A[i+1]至少选一个数,求能选出的最小和.
1 <= N <= 100000, 1 <= A[i] <= 1000
请为下面的Solution类实现解决上述问题的函数minSum,函数参数A是给出的数列,返回值为所求的最小和.
class Solution {
public:
int minSum(vector& A) {
}
};
例1:A = {2, 5, 2},答案为4.
例2:A = {2, 5, 4},答案为5.
注意:你只需要提交Solution类的代码,你在本地可以编写main函数测试程序,但不需要提交main函数的代码. 注意不要修改类和函数的名称.
比较容易往动态规划的方向想,一开始用递归的方法做结果超时了,改成循环就可以了。不得不说动态规划方法真的简洁优雅效率又高,就是要考虑清楚逻辑的完备性。状态转移方程如下,意思就是前i个数字的最小和有两种情况,一种包括第i个数字再加上前i-1个数字的最小和,另外一种包括第i-1个数字再加上前i-2个数字的最小和。要注意的是,比如说取了第i个数字不代表就不会取第i-1个数字,如2,5,2,1最优的情况是取2,2,1。
dp[i] = min(dp[i - 1] + A[i], dp[i - 2]+A[i-1]);
class Solution {
public:
int minSum(vector<int>& A) {
int *dp = new int[A.size()];
if (A.size() == 1) {
return A[0];
}
if (A.size() == 2) {
return min(A[0], A[1]);
}
if (A.size() == 3) {
min(A[0] + A[2], A[1]);
}
dp[0] = A[0];
dp[1] = min(A[0], A[1]);
dp[2] = min(A[0] + A[2], A[1]);
for (int i = 3; i < A.size(); i++) {
dp[i] = min(dp[i - 1] + A[i], dp[i - 2]+A[i-1]);
}
return dp[A.size() - 1];
}
};