leetcode:1746. 经过一次操作后的最大子数组和

题目来源

题目描述

你有一个整数数组 nums。你只能将一个元素 nums[i] 替换为 nums[i] * nums[i]。

返回替换后的最大子数组和。

示例 1:

输入:nums = [2,-1,-4,-3]
输出:17
解释:你可以把-4替换为16(-4*(-4)),使nums = [2,-1,16,-3]. 现在,最大子数组和为 2 + -1 + 16 = 17.

示例 2:

输入:nums = [1,-1,1,1,-1,-1,1]
输出:4
解释:你可以把第一个-1替换为1,使 nums = [1,1,1,1,-1,-1,1]. 现在,最大子数组和为 1 + 1 + 1 + 1 = 4.

实现:

class Solution {
public:
    int maximumSum(vector<int>& arr){
        
    }
};

题目解析

状态表示:操作即nums[i]替换为nums[i] * nums[i]

  • f(i, 0):以第i个数字为结尾,没有使用操作,最大子数组和
  • f(i, 1):以第i个数字结尾,已经使用操作,最大子数组和

状态转移:

  • 以第i个数字结尾,一次都没有操作,说明前i-1个数字也没有使用操作,所以由f(i - 1, 0)转移
  • 以第i个数字结尾,使用了操作,则有两种转移方式:
    • 前i-1个数字没有使用操作,但是第i个数字使用了操作,所以由f(i - 1, 0)转移
    • 前i-1个数字已经使用操作,所以由f(i - 1, 1)转移

小贪心,使用了操作肯定比没使用操作的状态大,所以最后汇总只需要在使用了的状态里取最大值

class Solution {
    struct Info{
        int noOperator;      // 不进行任何操作
        int replaceOne;  // 无论如何替换一次(可以替换i,或者替换i之前的数)
    };
public:
    int maximumSum(vector<int>& nums){
        int len = nums.size();
        std::vector<Info> dp(len);
        dp[0].noOperator = nums[0]; // 不进行任何操作,以nums[i]结尾, 能够得到的最大子数组和
        dp[0].replaceOne = nums[0] * nums[0]; // 此时,只能替换nums[0]
        int max = dp[0].replaceOne;
        for (int i = 1; i < len; ++i) {
            dp[i].noOperator = std::max( // 不进行任何操作:
                    nums[i],                       //  要么只要当前
                    nums[i] + dp[i - 1].noOperator  // 要么当前和之前联合
                    );
            dp[i].replaceOne = std::max(                    // 替换一次:
                    nums[i] * nums[i] + dp[i - 1].noOperator,  // 替换当前 + 之前不替换
                    nums[i] + dp[i - 1].replaceOne             // 不替换当前 + 替换之前
                    )  ;
            max = std::max(max, dp[i].replaceOne);
        }
        return max;
    }
};

类似题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值