力扣 53 最大子序和
全部刷题与学习记录
原题目
题目地址: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;
}
};
参考: