力扣 53 最大子序和【贪心】【暴力】

力扣 53 最大子序和

全部刷题与学习记录

【C++刷题学习笔记目录】

【C++百万并发网络通信-笔记目录】

原题目

题目地址:53. 最大子序和


考查知识点

贪心


自己的第一遍解法

最直观的就是暴力解法,两层嵌套for循环,类似滑动窗口一样,计算窗口内的序列之和

第一层循环:改变窗口移动位置

第二层循环:改变窗口尾端位置,不断扩大直至尾端对齐数组尾部

class Solution_01 {
    
    
public:
    int maxSubArray(vector<int>& nums) {
    
    
        if (nums.empty())   return 0;
        if (nums.size() == 1)   return nums.front();

        int maxSum = INT32_MIN;//最大和
        int count = 0;//累加和

        //特殊情况:最后一个数字单独作为数组
        if (nums.back() > maxSum)   maxSum = nums.back();
        //使用滑动窗口统计窗口内累加和的最大值
        for (int i = 0; i < nums.size() - 1; i++) {
    
    
            count = nums[i];
            //特殊情况:每个数字单独作为数组
            if (count > maxSum) maxSum = count;
            for (int j = i + 1; j < nums.size(); j++) {
    
    
                count += nums[j];
                if (count > maxSum) maxSum = count;
            }
        }
        return maxSum;
    }
};

需要注意的是,上面这种写法因为j是从i+1开始,所以必然i就不能取到数组的最后一个数字,需要单独考虑最后一个数字单独作为数组的情况,另外还需要考虑数组中每个数字也能单独作为数组的情况


好的解法

暴力解法时间复杂度是O(n^2),效率很低,【代码随想录】大佬给出了一种贪心解法,概括来说就是:count为负数的情况,就马上把count归零,从下一个数字开始重新累加,相当于暴力解法的第一层循环(改变窗口起点)。因为count<0时,如果继续累加下一位数字,加和一定会小于刚加上的这个数字本身。

class Solution {
    
    
public:
    int maxSubArray(vector<int>& nums) {
    
    
        int res = INT32_MIN;
        int count = 0;

        for (int i = 0; i < nums.size(); i++) {
    
    
            count += nums[i];
            if (count > res)// 取区间累计的最大值(相当于不断确定最大子序终止位置)
                res = count;
            if (count <= 0) // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
                count = 0;
        }
        return res;
    }
};

参考:

贪心算法:最大子序和

猜你喜欢

转载自blog.csdn.net/weixin_44484715/article/details/113815830