我正在参加「掘金·启航计划」
1. 联想实际场景
首先我们能想到的实际场景就是股票交易,即根据历史交易数据,在哪个点买入,持有多久,可以挣到最多的钱。这对该股票的投资有一定的指导性。
当然这里的指导是两方面的,就像题目中提到的,如果考察的时间区间一直下跌。那可能不持有该股票是最好的选择。
你也许会说,利用既成的事实去模拟实际的股票交易,是否是纸上谈兵。诚然,这种担心不无道理,过去的绩效并不能代表预期很好,但确实在股票呈现周期性波动时,这种分析可以作为一个重要的参考。
2.我的思路
我首先想到,最大子序和应该是从一个正整数开始,所以我会先找到起点。然后再利用变成负数肯定不是最大的思想,来进行编码。期间我学习了 《【C/C++】Maximum Subsequence Sum/最大子列和问题》 的思路。
2.1.我的代码
#include <iostream>
using namespace std;
int main() {
int k;
int nums[100000];
bool allNegative = true;
cin>>k;
for(int i=0; i<k; i++) {
cin>>nums[i];
if(nums[i]>0){
allNegative = false;
}
}
if(allNegative){
return 0;
}
int left = 0;
long maxSum = 0;
while(nums[left]<0){
left++;
}
long cSum = 0;
for(int i=left;i<k;i++){
cSum += nums[i];
if(cSum>maxSum){
maxSum=cSum;
}
if(cSum<0){
cSum = 0;
}
}
cout<<maxSum<<endl;
return 0;
}
3.总结收获
3.1. 可以在输入时判定状态
算法题目要求我们尽量减少时间和空间的消耗,如果两件事能同步进行,就不再单独分别进行。本题目中,输入测试数据时也可以判断是否所有数据都是负数。
3.2. 判断临界状态而不是中间结果
本题最难想通的部分就是:当一个子序列和出现了负数,应立即抛弃这段和,从下一段子序列中寻找最大的和。但就像我前面提到的实际场景,如果你意识到了抽象题目对应的实际场景,这就很容易想到。也就是当你手中持有的股票跌到亏损状态,从之前某一天就开始持有的情况必然不是最大收益的情况,要从后面的日子寻找新的机会了。