1. 题目来源
2. 题目解析
一道不错的 T2,直接上来就是 dp。想着会不会是一个贪心题目,就写了写,WA 了 2 发后实在顶不住了,换个思路考虑,dp,秒过…
思路:
- 状态定义:f[i][j]:选到 i 位置时,且选择 j 饮料的最大值。j 在这里只能去 0,1 代表 a、b 两种饮料。
- 状态转移,思考方式1:
- f[i][0] = max(f[i-1][0]+a[i), f[i-1][1]); 代表 如果走到了 a[i] 这个位置,那么状态必然由 a[i-1] 或者 b[i-1] 转移过来。如果是 a[i-1] 的话,可以将 f[i-1][0] 累加起来,因为是同种饮料。如果是 b[i-1] 的话,那么当前的这个 a[i] 实际上是不可选的,因为是饮料切换。但是可以继承 f[i-1][1] 另一种饮料的最大值。
- 另一种同理。
- 状态转移,思考方式2:
- f[i][0]=max(f[i-1][0]+a[i], f[i-2][1]+a[i]); 这个思考方式是从 i 的转移过程来考虑,他前一个肯定是从 当前饮料的 i-1 或者另一个饮料的 i-2 处过来的。
至于状态初始值的定义,因为第二种状态转移思路有个 i-2 这个操作,且当 i=1 的时候,i-2 还是会受到这个影响,此时可以考虑将空间统一开大一个,做一下偏移即可,也是一个常用技巧吧。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)
仅考虑前一位的状态转移:
class Solution {
public:
long long maxEnergyBoost(vector<int>& energyDrinkA, vector<int>& energyDrinkB) {
typedef long long LL;
int n = energyDrinkA.size();
LL f[n][2];
f[0][0] = energyDrinkA[0]; f[0][1] = energyDrinkB[0];
for (int i = 1; i < n; i ++ ) {
// 对于第 i 杯饮料。
// i 喝了,意味着 i-1 也喝了。 状态为:f[i-1][0] + a[i]
// i 不喝,则 i-1 喝的是另一种,饮料品类变化,次轮不加当前值。状态为:f[i-1][1]
f[i][0] = max(f[i - 1][0] + energyDrinkA[i], f[i - 1][1]);
f[i][1] = max(f[i - 1][1] + energyDrinkB[i], f[i - 1][0]);
}
return max(f[n - 1][0], f[n - 1][1]);
}
};
考虑前两位的状态转移:
class Solution {
public:
long long maxEnergyBoost(vector<int>& energyDrinkA, vector<int>& energyDrinkB) {
typedef long long LL;
int n = energyDrinkA.size();
LL f[n + 1][2];
memset(f, 0, sizeof(f));
f[1][0] = energyDrinkA[0];
f[1][1] = energyDrinkB[0];
for (int i = 2; i <= n; ++i) {
f[i][0] = max(f[i - 1][0], f[i - 2][1]) + energyDrinkA[i - 1];
f[i][1] = max(f[i - 1][1], f[i - 2][0]) + energyDrinkB[i - 1];
}
return max(f[n][0], f[n][1]);
}
};
原生,未额外开辟数组:
class Solution {
public:
long long maxEnergyBoost(vector<int>& energyDrinkA, vector<int>& energyDrinkB) {
typedef long long LL;
int n = energyDrinkA.size();
LL f[n + 1][2];
memset(f, 0, sizeof(f));
f[1][0] = energyDrinkA[0];
f[1][1] = energyDrinkB[0];
for (int i = 2; i <= n; ++i) {
f[i][0] = max(f[i - 1][0], f[i - 2][1]) + energyDrinkA[i - 1];
f[i][1] = max(f[i - 1][1], f[i - 2][0]) + energyDrinkB[i - 1];
}
return max(f[n][0], f[n][1]);
}
};