版权声明:本文为博主原创文章,未经允许不得转载。 https://blog.csdn.net/Koala_Tree/article/details/79728591
题目一:股票的最大利润(一次卖出)
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可获得的最大利润是多少?
例子:
例如,一只股票在某些时间节点的价格为{9,11,8,5,7,12,16,14}。如果我们能在价格为5的时候买入并在价格为16时卖出,则能获得最大的利润为11.
链接:
剑指Offer(第2版):P304
LeetCode-121:Best Time to Buy and Sell Stock (一次股票交易最大利润)
思路标签:
- 记录当前最小值和最大差值
解答:
- 最大利润无外乎就是计算后面的数字减去前面的数字得到的一个最大的差值;
- 求总体的最大差值,需要的数据:当前的最小值,当前的最大差值;遍历求解即可。
class Solution {
public:
int maxProfit(vector<int> prices) {
int length = prices.size();
if (length < 2)
return 0;
int minPrice = prices[0];
int maxDiff = prices[1] - minPrice;
for (int i = 2; i < length; ++i) {
if (prices[i - 1] < minPrice)
minPrice = prices[i - 1];
int currentDiff = prices[i] - minPrice;
if (currentDiff > maxDiff)
maxDiff = currentDiff;
}
return maxDiff;
}
};
题目二:股票的最大利润(多次卖出)
与题目一不同的是,这里可以多次卖出。
链接:
LeetCode-122:Best Time to Buy and Sell Stock II (多次股票交易最大利润)
思路标签:
- 前一天买入,盈利则第二天卖出
解答:
- 可以对股票进行多次的买入和卖出;
- 则如果第二天的价格高于第一天的价格就可以以第二天的价格卖出,则卖出后立即再次买入;
- 如果第二天的价格低于第一天的价格,那么就在第一天结束前就卖出,相当于不盈利。
- 所以通过逐个相邻两数进行比较即可,如果后面的大,则记为利润。
class Solution {
public:
int maxProfit(vector<int> prices) {
int length = prices.size();
if (length < 2)
return 0;
int maxProfit = 0;
for (int i = 0; i < length - 1; i++) {
int profit = prices[i + 1] - prices[i];
if (profit > 0)
maxProfit += profit;
}
return maxProfit;
}
};
题目三:股票的最大利润(至多两次交易)
与题目一不同的是,这里做出了限制,最多实现两次交易。
链接:
LeetCode-123:Best Time to Buy and Sell Stock III
思路标签:
- 前i天的最大利润和i天后的最大利润和
解答:
1. 分段考虑
- 以i为分界线,前i天的最大和i天后面的最大,分两段进行每次的一个交易;
- 两段的最大和,则为最大的利润;
class Solution {
public:
/**
* 计算最大收益
* @param prices : 每日价格
* @return : 最大收益
* @note : 至多进行两次买卖
*/
int maxProfit(vector<int>& prices) {
int pricesSize = prices.size();
/* 如果价格数据为空或只有一个数据,返回0 */
if (pricesSize <= 1) return 0;
vector<int> maxProfitDuringFormmerDays(pricesSize),
maxProfitDuringLatterDays(pricesSize);
int day, diff, minPrice, maxPrice, maxProfit;
/* 计算某一天极其之前所有时间内的最大利益 */
minPrice = prices[0];
maxProfit = 0;
maxProfitDuringFormmerDays[0] = 0;
for (day = 1; day < pricesSize; ++day) {
diff = prices[day] - minPrice;
if (diff < 0) minPrice = prices[day];
else if (diff > maxProfit) maxProfit = diff;
maxProfitDuringFormmerDays[day] = maxProfit;
}
/* 计算某一天极其之后所有时间内价格的最利益 */
maxPrice = prices[pricesSize - 1];
maxProfit = 0;
maxProfitDuringLatterDays[pricesSize - 1] = 0;
for (day = pricesSize - 2; day > -1; --day) {
diff = maxPrice - prices[day];
if (diff < 0) maxPrice = prices[day];
else if (diff > maxProfit) maxProfit = diff;
maxProfitDuringLatterDays[day] = maxProfit;
}
/* 计算最大收益 */
int sum;
maxProfit = 0;
for (day = 0; day < pricesSize; ++day) {
sum = maxProfitDuringFormmerDays[day] + maxProfitDuringLatterDays[day];
if (sum > maxProfit) maxProfit = sum;
}
return maxProfit;
}
};
2. 动态规划的思想
Buy1[i]表示前i天做第一笔交易买入股票后剩下的最多的钱;
Sell1[i]表示前i天做第一笔交易卖出股票后剩下的最多的钱;
Buy2[i]表示前i天做第二笔交易买入股票后剩下的最多的钱;
Sell2[i]表示前i天做第二笔交易卖出股票后剩下的最多的钱;
那么:
- Sell2[i]=max{Sell2[i-1],Buy2[i-1]+prices[i]}
- Buy2[i]=max{Buy2[i-1],Sell[i-1]-prices[i]}
- Sell1[i]=max{Sell[i-1],Buy1[i-1]+prices[i]}
- Buy1[i]=max{Buy[i-1],-prices[i]}
可以发现上面四个状态都是只与前一个状态有关,所以可以不使用数组而是使用变量来存储即可。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int buy1=numeric_limits<int>::min();
int buy2=numeric_limits<int>::min();
int sell1=0;
int sell2=0;
for(int i=0;i<prices.size();i++)
{
sell2=max(sell2,buy2+prices[i]);
buy2=max(buy2,sell1-prices[i]);
sell1=max(sell1,buy1+prices[i]);
buy1=max(buy1,-prices[i]);
}
return sell2;
}
};