最大子序列之和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

1.使用动态规划:

对于该问题,假设以nums[i]结尾的最大连续子序列为dp[i],那么存在下列两种情况:

1,最大连续子序列为nums[i]本身,即只存在一个元素,此时dp[i]=nums[i];

2,最大连续子序列是nums[i]+dp[i-1],其中dp[i-1]为nums[i-1]结尾的最大连续子序列和,此时d[i]=nums[i]+dp[i-1]。

因为以nums[i]结尾的最大连续子序列的末尾元素只能为nums[i],故仅存在上述两种情况,故可总结出状态转移方程:

                            dp[i] = max(nums[i], nums[i] + dp[i-1])

对应的代码如下:

(1)提前处理i=0的情况:
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT_MIN;
        int current_dp = nums.at(0), last_dp = nums.at(0);
        result = nums.at(0); //需要特别注意i=0的情况,否则全部是负数就出错
        for (int i = 1; i < nums.size(); ++i) {
            current_dp = std::max(nums.at(i), last_dp + nums.at(i));
            last_dp = current_dp; //可以优化只是用一个变量
            if (current_dp > result) {
                result = current_dp;
            }
        }
        return result;
    }
};
(2)单独处理i=0的情况:
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT_MIN;
        int current_dp = nums.at(0), last_dp = nums.at(0);
        int temp_sum = 0;
        for (int i = 0; i < nums.size(); ++i) {
            if (0 == i) { //单独处理第一个数字,保障全部都是负数正确,例如[-1,-2]
                current_dp = nums.at(0);
                last_dp = nums.at(0);
            } else {
                current_dp = std::max(nums.at(i), last_dp + nums.at(i));
                last_dp = current_dp; //可以优化只是用一个变量
            }
            if (current_dp > result) {
                result = current_dp;
            }
        }
        return result;
    }
};

2.使用贪心算法:

如果 temp_sum > 0,则说明 temp_sum  对结果有增益效果,则 temp_sum  保留并加上当前遍历数字

如果 temp_sum  <= 0,则说明 temp_sum  对结果无增益效果,需要舍弃,则 temp_sum  直接更新为当前遍历数字

每次比较 temp_sum  和 result的大小,将最大值置为result,遍历结束返回结果

对应的代码如下:

class Solution
{
public:
    int maxSubArray(vector<int> &nums) {
        int result = INT_MIN;
        int temp_sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            temp_sum += nums[i]; //只要和大于0,都有希望超于最大值
            result = max(result, temp_sum);
            //如果temp_sum < 0,重新开始找子序串
            if (temp_sum < 0) { //代表之前的数据贡献为负,需要重置
                temp_sum = 0;
            }
        }
        return result;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值