开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第33天,点击查看活动详情
LeetCode 121. Best Time to Buy and Sell Stock
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
提示:
1 <= prices.length <= 1050 <= prices[i] <= 104
算法1
(贪心或单调栈都可以) O(n) 维护i之前最小的买入价格,维护在i处卖出的最大收益
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
if(n<2) return 0;
int low=prices[0],profit=0;
for(int i=1;i<n;i++)
{
low=min(low,prices[i]);
profit=max(prices[i]-low,profit);
}
return profit;
}
};
算法2
(动态规划-状态机) O(n)
-
状态表示:f[i][0]表示在第i天手里无股票最大收益,f[i][1]表示手里有股票的最大收益
这里只能进行一次交易,所以用户手上不持股所能获得的最大利润,特指卖出股票以后的不持股, 非指没有进行过任何交易的不持股 -
状态计算:f[i][0]=max(f[i-1][0],f[i-1][1]+prices[i]);
f[i][1]=max(f[i-1][0],-prices[i]);
注意:因为题目只允许一次交易,因此不能加上 dp[i - 1][0],加上的话可能会多次交易
3.边界问题:第0天时持股为f[0][1]=-price[0]; 无股为f[0][0]=0;
ac代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n=prices.size();
if(n<2) return 0;
int f[n+1][2];
f[0][0]=0,f[0][1]=-prices[0];
for(int i=1;i<n;i++)
{
f[i][1]=max(f[i-1][1],-prices[i]);
f[i][0]=max(f[i-1][0],f[i-1][1]+prices[i]);
}
return f[n-1][0];
}
};