DP
以每个位置为结尾的序列的分数取决于前方的分数,根据奇偶性计算,取最大值
超时
class Solution {
public long maxScore(int[] nums, int x) {
int n = nums.length;
long dp[] = new long[n];
Arrays.fill(dp, Integer.MIN_VALUE);
dp[0] = nums[0];
long res = nums[0];
for(int i = 1; i < n; i ++){
for(int j = 0; j < i; j ++){
if(nums[j] % 2 == nums[i] % 2){
dp[i] = Math.max(dp[i], dp[j] + nums[i]);
}
else{
dp[i] = Math.max(dp[i], dp[j] + nums[i] - (long)x);
}
}
res = Math.max(res, dp[i]);
}
return res;
}
}
优化
对于 nums[ i ] 来说,该位置的分数取决于前方的序列分数,分为上一个选择是奇数和偶数两种情况,只需max0、max1来分别记录前方的奇偶两种情况最值即可计算出当前位置的分数最值
避免思维误区,计算cur时考虑的不是选或不选的两种情况,而是必定选择 nums[ i ] 作为序列最后一个元素时,取前方奇偶两种可能所获得的分数哪一种更大
由于存在x值较大的情况,计算中可能出现负数,将max0、max1初始化为INT_MIN
获取最值后根据 nums[ i ] 的奇偶性选择更新max0或max1
计算max0/1的两种可能时,即使有可能异性-x后的分数更大,但由于存在同性计算 — 两个正数相加,因此max0/1的值必定会增大,直接将cur赋值给max0/1
class Solution {
public long maxScore(int[] nums, int x) {
int n = nums.length;
long max0 = Integer.MIN_VALUE; // 前方偶数结尾的最大分数
long max1 = Integer.MIN_VALUE; // 前方奇数结尾的最大分数
if(nums[0] % 2 == 0)
max0 = nums[0];
else
max1 = nums[0];
long res = nums[0];
for(int i = 1; i < n; i ++){
long cur;
if(nums[i] % 2 == 0){
cur = Math.max(max0 + nums[i], max1 + nums[i] - x);
max0 = cur;
// max0 = Math.max(max0, cur);
// 同性情况max0+nums[i],正数求和计算导致cur必然大于max0,省去Max计算
}
else{
cur = Math.max(max0 + nums[i] - x, max1 + nums[i]);
max1 = cur;
}
res = Math.max(res, cur);
}
return res;
}
}