算法题(146):最大子段和
、
审题:
本题需要我们找到给定数组中子段之和和最大的sum值思路:
方法一:暴力解法
我们可以使用双层for循环,第一层循环负责遍历每一个数组元素,然后分别以他们为子段起点,第二层循环从第一层循环的索引开始接着往下遍历累加结果到sum中,且遍历的时候不断用max方法让sum与answer进行比对,如果出现sum小于0就停止当前子段和的搜索,因为
即使后面的数再大,我们前面的sum也对后面的数产生了负作用。
方法二:贪心其实我们不需要进行两层for循环,一旦出现sum小于0,说明前面一段的所有元素都不可能是最大子段和的开头索引。
贪心策略:从开头索引开始进行遍历,一旦sum小于0就将sum置为0,接着往下遍历
贪心策略证明:
假设出现了sum小于0的那一段元素存在最大子段和的初始索引
情况1:最大子段在sum内
Sak<Sck,所以Sak-Sck < 0,即Sac<0。而ac段的总和不会小于0,因为如果他小于0(也就是此时sum就小于0了),那么就不会存在Sab段,直接在Sac段就截断了
情况2:最大子段不全在sum内
我们知道:Scb>Sab
若Sab>Scb,最大子段和的开始位置就是a
而此时由于Sac+Scb = Sab,我们得出Sac又要小于0,同理此时也是不合理的
综上:最大子段和的开始位置不会出现在sum小于0的数据段中,可以直接舍弃
解题:
#include<iostream> #include<algorithm> using namespace std; const int N = 2e5 + 10; typedef long long ll; int n; int a[N]; ll answer = -1e7; ll sum; int main() {//数据录入cin >> n;for (int i = 1; i <= n; i++){cin >> a[i];}//遍历查找for (int i = 1; i <= n; i++){sum += a[i];answer = max(sum, answer);if (sum < 0)sum = 0;}cout << answer << endl;return 0; }
P1115 最大子段和 - 洛谷