每日写题分享--K次取反后最大化的数组和//动态规划

题目描述:

题目链接戳此 

思路:

这题我是用动态规划做的,主要是想练习一下动态规划,但是实际写题中这题不太建议用动规。

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];
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值