LeetCode 121. Best Time to Buy and Sell Stock

85 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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 <= 105
  • 0 <= 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)

  1. 状态表示:f[i][0]表示在第i天手里无股票最大收益,f[i][1]表示手里有股票的最大收益

          这里只能进行一次交易,所以用户手上不持股所能获得的最大利润,特指卖出股票以后的不持股,
          非指没有进行过任何交易的不持股
    
  2. 状态计算: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];
    }
};