中秋快乐&&股市飘红--- Best Time to Buy and Sell Stock III&& II&&I

来源:互联网 发布:矩阵的平方 编辑:程序博客网 时间:2024/05/22 00:34

题目大意

     给定一个数组a,a[i]表示第i天的股票价格,求:

     I.若只交易一次,获利最大值。

II.若交易任意次,获利最大值。

III.若最多交易两次,获利最大值。

解题思路

     前两天刷了I和II,然后正好碰上中秋佳节,在家爽了两天后回来又把III给过了,又正好赶上股票大涨,这题还真是应景,在此抓住中秋的尾巴祝各位中秋快乐。废话少说,开始撸题。(我发现撸这个字颇有深意,完全可以取代搞这个神级词汇(0-0)!)。。。

I、若只允许交易一次,显然只要低买高卖、投机倒把就行了,但是单从题目给定的数据来看无法准确获取到最大的落差,因此这里卡了一小会儿,但是在我吃完中饭集满查克拉之后,我突然发现可以处理一下原来的数组,将其相邻数值相减可以直接得到每相邻交易的成本差值,这样就能得到一个n-1的数组,就是每次交易(相邻两天的交易,即第一天买后一天卖)的获利(可能为负数),然后就简单了,只要求一次最大连续和就能得到题目的解。是不是很简单?

II、看懂了I,II就比较简单了,显然我只要保证每次都获利那就肯定是最大值了,基本的贪心思路,因此只要将所有获利为正数的求和就能得到解。

III、这题应该是这个股票系列里面最难的一道了,只允许最多交易两次,这个最多很是奇怪,所以纠结了一小会儿,最初想到是不是前两个最大的获利连续和,但是怎么都没有想出来如何求得这两个最大的获利连续和(因为两个连续和序列之间不能相交,而且可能出现相同的情况,因此编码并不是十分容易),后来想着牺牲一点时间来实现,对每一个点考虑为截断点,然后前后各求一次最大连续和,这样时间复杂度为O(n^2),结果TLE。。FUCK!!。。没办法,想想能不能压缩复杂度,显然这个计算有太多的重复运算了,我每次都得重新计算已经计算过的连续最大和,那么为何不使用两个数组分别记录第i个截断点前,后的最大连续和呢?果然这样一处理就变成了O(n)的复杂度,成功解决了。

总结

      先得大略,逐步求精

代码

I:

class Solution {public:    int maxProfit(vector<int> &prices)     {        int n = prices.size();        int profit = INT_MIN;        int sum = 0;        for (int i = 1 ; i < n; i ++){            prices[i-1] = prices[i]-prices[i-1];        }        for (int i = 0 ; i < n-1; i ++){            sum += prices[i];            profit = max(profit, sum);                   if (sum < 0)sum = 0;        }        return profit < 0?0:profit;    }};

II:

class Solution {public:    int maxProfit(vector<int> &prices)     {        int n = prices.size();        int profit = 0;        int sum = 0;        for (int i = 1 ; i < n; i ++){            prices[i-1] = prices[i]-prices[i-1];        }        int temp = INT_MIN;        for (int i = 0 ; i < n-1; i ++){            if (prices[i] > 0)  profit += prices[i];        }        return profit < 0?0:profit;    }};

III:

class Solution {public:    int maxProfit(vector<int> &prices)     {        int n = prices.size();        int profit1 = INT_MIN, profit2 = INT_MIN;        int before[100010], after[100010];        memset(before,0,sizeof(before));        memset(after,0,sizeof(after));        int sum1 = 0, sum2 = 0;        for (int i = 1 ; i < n; i ++){            prices[i-1] = prices[i]-prices[i-1];        }        for (int i = 0 ; i < n-1; i ++){            sum1 += prices[i];            sum2 += prices[n-2-i];            profit1 = max(profit1, sum1);            profit2 = max(profit2, sum2);            before[i] = profit1;            after[n-2-i] = profit2;            if (sum1 < 0)sum1 = 0;            if (sum2 < 0)sum2 = 0;        }        int ans = INT_MIN;        for (int i = 0; i < n-1; i ++){            if (i != n-2 && i != 0)  ans = max(ans, before[i]+after[i+1]);            if (i == 0) ans = max(ans, after[i]);            if (i == n-2) ans = max(ans,before[i]);                    }        return ans < 0?0:ans;    }};


0 0