您的位置:首页 > 编程语言 > C语言/C++

【Best Time to Buy and Sell Stock III 】cpp

2015-06-02 14:18 316 查看
题目:

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

代码:

class Solution {
public:
int maxProfit(vector<int>& prices) {
if (prices.empty()) return 0;
const int len = prices.size();
vector<int> l(len,0),r(len,0);
// from left to right
l[0] = 0;
int l_min = prices[0];
for ( int i = 1; i < l.size(); ++i )
{
l_min = std::min(l_min, prices[i]);
l[i] = std::max(l[i-1], prices[i]-l_min);
}
// from right to left
r[len-1] = 0;
int r_max = prices[len-1];
for ( int i = len-1; i >= 0; --i )
{
r_max = std::max(r_max, prices[i]);
r[i] = std::max(r[i-1], r_max-prices[i]);
}
// travseral the best two times
int max_profit = 0;
for ( int i = 0; i < prices.size(); ++i )
{
max_profit = std::max(max_profit, l[i]+r[i]);
}
return max_profit;
}
};


tips:

此题说最多交易两次,求最大获利。

直觉的想法就是,把整个时间段分割成两部分( 共有prices.size()种分类方法 );分好后分别求两部分各自的最大值;这种算法是O(n²)时间复杂度的。

模仿之前求过的largest rectangle in histogram这道题的思路,能否利用dp思想,把算过的中间结果都存起来,把时间复杂度降低到O(n)。

想到这个思路就比较明确了:

1. 从左向右走一遍,l[i]存放0~i最多交易1次获利最大的值

2. 从右向左走一遍,r[i]存放i~prices.size()-1最多交易一次获利的最大值

3. 遍历数组l和数组r,通过遍历每种分割情况下的最大获利,并最终获得最终的最大获利值。

这里还有个细节可能会产生疑义:如果以第i天作为分割点,那么这第i天是算到前半截还是后半截呢?

这里分两种情况:

1. 如果“前半截的最大利润”和“后半截的最大利润”只有一截涉及到了第i天,显然l[i]+r[i]这个算法是没问题的

2. 如果“前”、“后”两截都涉及到了第i天呢?这时候有两种理解方法:

  2.1 前后交易两次:前半截的某一天买入,第i天卖了,挣一笔;第i天卖完又买入了,到后面的某一天又卖了,挣第二笔。两笔加起来最大。

  2.2 前后交易一次:前半截的某一天买入,第i天虽然卖了获利最大,但是不卖,留着;等到后面的某一天发现获利最大,直接挣一笔最大的,同样获利最大。

因此,无论按照哪种理解方法,l[i]+r[i]都是合理的,不会因为第i天作为分割点而产生影响。

=====================================================

第二次过这道题,思路上有个地方没有理清(红字),在当天可以选择交易或者不交易,如果不交易那么等于左边(或右边)相邻元素的值。

class Solution {
public:
int maxProfit(vector<int>& prices) {
if ( prices.empty() ) return 0;
vector<int> l(prices.size(), 0);
vector<int> r(prices.size(), 0);
// l
int minPrices = prices[0];
for ( int i=1; i<prices.size(); ++i )
{
minPrices = min(prices[i], minPrices);
l[i] = max(l[i-1], prices[i]-minPrices);
}
// r
int maxPrices = prices[prices.size()-1];
for ( int i=prices.size()-2; i>=0; --i )
{
maxPrices = max(maxPrices, prices[i]);
r[i] = max(r[i+1], maxPrices - prices[i]);
}
// l to r
int ret = 0;
for ( int i=0; i<prices.size(); ++i )
{
ret = max(ret, l[i]+r[i]);
}
return ret;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: