PTA-最大子列和问题

97 阅读2分钟

我正在参加「掘金·启航计划」

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. 判断临界状态而不是中间结果

  本题最难想通的部分就是:当一个子序列和出现了负数,应立即抛弃这段和,从下一段子序列中寻找最大的和。但就像我前面提到的实际场景,如果你意识到了抽象题目对应的实际场景,这就很容易想到。也就是当你手中持有的股票跌到亏损状态,从之前某一天就开始持有的情况必然不是最大收益的情况,要从后面的日子寻找新的机会了。