Leetcode-53. 最大子序和

14 篇文章 2 订阅

方法一:分治法(处理线段树的)

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        return findMax(nums, 0, nums.size()-1);
    }

    // 分治算法求解
    // 思路就是把这个问题分成三部分:1、求左边[0, middle-1]这个闭区间部分的max;2、求右边[middle+1, nums.size()-1]这个闭区间部分的max;
    // 和3、跨越中间元素部分的max(这部分是从左边跨越的max + 中间元素的值(即nums[middle]) + 从右边跨越的max)。
    // 然后比较三个部分,哪个部分是最大值,就是最终的题解。

    int findMax(vector<int>& nums, int start, int end)
    {
        // 判断边界条件
        if(start == end) return nums[start];
        if(start > end) return INT_MIN;

        int left_max, right_max; // 分别定义第一部分的解和第二部分的解
        int middle = (start + end) / 2; // 找出这个数组中间元素的位置
        int left_sum = 0, right_sum = 0, mid_to_left_max = 0, mid_to_right_max = 0; // 定义从左边跨越的max和从右边跨越的max
        // 注意:mid_to_left_max和mid_to_right_max的初始值定义为0就好,因为如果从左跨越和从右跨越都没有比0大的,
        // 那这两部分就直接是0就好了,最后和nums.[middle]加起来也还是中间值本身,没有问题。
        // 不可以定义为INT_MIN!!!不然很容易就会越界的。

        left_max = findMax(nums, start, middle-1); // 第一部分
        right_max = findMax(nums, middle+1, end); // 第二部分

        for(int i=middle-1; i>=start; i--)
        {
            // 第三部分 -> 从左边跨越
            left_sum += nums[i];
            if(mid_to_left_max < left_sum) mid_to_left_max = left_sum;
        }

        for(int i=middle+1; i<=end; i++)
        {
            // 第三部分 -> 从右边跨越
            right_sum += nums[i];
            if(mid_to_right_max < right_sum) mid_to_right_max = right_sum;
        }

        return (max(max(left_max, right_max), mid_to_left_max + mid_to_right_max + nums[middle]));
    }
};

方法二:动态规划

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0, maxAns = nums[0];
        for (const auto &x: nums) {
            pre = max(pre + x, x);
            maxAns = max(maxAns, pre);
        }
        return maxAns;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值