题目描述:
思路:
这题我是用动态规划做的,主要是想练习一下动态规划,但是实际写题中这题不太建议用动规。
1.首先题目求的是K次取反后最大化数组和,说明就有k-1次,k-2次。然后求得是数组和,那么就有0-len的数组和,0-len-1的数组和,而且肯定是有关联的。每一步求出来的值都和前一步有关系,那么就说明这题可以使用动态规划去求解。
2.既然要使用动态规划,第一步是定义状态,由于涉及到了k次取反,又涉及到了数组求和,所以动规数组肯定是二维数组--dp[k][len+1]。那么我们就可以定义dp[i][j]为下标0-i,取反j次之后的最大数组和。
第二步就是状态方程了,状态方程主要是找到和前面的关联就好。在这题中,要在0-i下标中取反j次的情况下,有两种做法。
<1>先看i - 1取反了几次,如果0-i取反了j次那么在i下标就不需要取反了。求数组和直接再加上array[i]就好。
<2>如果0到i-1取反了j-1次,那么在i下标还要再取反一次。意思就是array[i]变成了-array[i],那么数组和就是再-array[i]。
题目要求数组最大和,所以0-i取反j次的值就是上面两种情况的最大值。即
dp[i][j] = Math.max(dp[i - 1][j - 1] - nums[i],dp[i - 1][j] + nums[i]);
第三步初始化。下标0到0,取反0次的最大的数组和,就是array[0]。
下标0到0,取反i次的最大的数组和,就是- dp[0][i - 1]。
下标0到i,取反0次的最大的数组和,就是dp[i - 1][0] + array[i]。
接下来就是代码实现了:
class Solution {
public int largestSumAfterKNegations(int[] nums, int k) {
//定义状态:dp[i][j]表示下标0到i取反j次的最大的数组和
int[][] dp = new int[nums.length][k+1];
//初始化:下标0到0,取反0次的最大的数组和
dp[0][0] = nums[0];
//初始化:下标0到0,取反i次的最大的数组和
for (int i = 1;i < k + 1;i++) {
dp[0][i] = - dp[0][i - 1];
}
//初始化:下标0到i,取反0次的最大的数组和
for (int i = 1;i < nums.length;i++) {
dp[i][0] = dp[i - 1][0] + nums[i];
}
for (int i = 1;i < nums.length;i++) {
for (int j = 1; j < k + 1;j++) {
dp[i][j] = Math.max(dp[i - 1][j - 1] - nums[i],dp[i - 1][j] + nums[i]);
}
}
return dp[nums.length - 1][k];
}
}