LeetCode 买卖股票的最佳时机

2,506 阅读3分钟

买卖股票的最佳时机

  • 根据题目,得知只能进行一次交易,即只能买一次、卖一次。有可能长期持有一支低价的股票,等到最后高价时卖掉。
  • 定义buy为买入股票的收入,sell为卖出股票的收入,buy+prices[i]为每日卖出股票的收入。
  • 可以得出两个公式:
    • sell = Math.max(sell,buy+prices[i])
    • buy = Math.max(buy,-prices[i])
  • 具体代码如下
var maxProfit = function(prices) {
    var buy = -prices[0],sell = 0;
    for(var i = 1;i<prices.length;i++){
        sell = Math.max(sell,buy+prices[i]);
        buy = Math.max(buy,-prices[i]);
    }
    return sell;
};

买卖股票的最佳时机 II

  • 根据题意,得知可以进行多次交易,所以可以多次买入,多次卖出。
  • 所以定义buy为买入股票的收入,sell为卖出股票的最终收入buy+prices[i]为每日卖出股票的收入。
  • 可以得出两个公式:
    • sell = Math.max(sell,buy+prices[i]+sell)
    • buy = -prices[i]
  • 具体代码如下
var maxProfit = function(prices) { 
    var buy = -prices[0],sell = 0; 
    for(var i = 1;i<prices.length;i++){ 
        sell = Math.max(sell,buy+prices[i]+sell); 
        buy = -prices[i]; 
    } 
    return sell; 
};

买卖股票的最佳时机 III

  • 根据题意,最多可以完成两次交易。每天可能有5中状态
    1. 没有进行任何交易
    2. 买入一支股票
    3. 完成一次交易
    4. 完成一次交易,然后买入一支股票
    5. 完成两次交易
  • 上述状态中,没有进行任何交易最终的结果是0,可以忽略这种状态。所以可以定义如下几个变量:
    • buy1:买入一支股票
    • sell1:完成一次交易
    • buy2:完成一次交易,然后买入一支股票
    • sell2:完成两次交易
  • 如何确定这4个变量的关系
    • 买入一支股票。假设每天都要买一支股票,即:buy=-prices[i]。我们需要求最大值,所以需要和上次的买入时做对比,即:buy1 = Math.max(buy1,-prices[i])
    • 完成一次交易。完成一次交易的公式是:sell=buy+prices[i]。所以:sell1 = Math.max(sell1,buy1+prices[i])
    • 完成一次交易,然后买入一支股票。因为已经完成一次交易,所以再买入一支股票的结果是:buy=sell-prices[i]。所以:buy2 = Math.max(buy2,sell1-prices[i])
    • 完成两次交易完成一次交易类似,所以:sell2 = Math.max(sell2,buy2+prices[i])
  • 具体代码如下
var maxProfit = function(prices) {
    var buy1 = -prices[0],buy2 = -prices[0],sell1 = 0,sell2 = 0;
    for(var i = 1;i<prices.length;i++){
        buy1 = Math.max(buy1,-prices[i]);
        sell1 = Math.max(sell1,buy1+prices[i]);
        buy2 = Math.max(buy2,sell1-prices[i]);
        sell2 = Math.max(sell2,buy2+prices[i]);
    }
    return sell2;
};

买卖股票的最佳时机 IV

  • 本题和买卖股票的最佳时机 III类似,从最多可以完成两次交易,变成最多可以完成k次交易。
  • 我们对比买卖股票的最佳时机 III2次交易有4种状态,所以k次交易有2*k种状态。
  • 2*k种状态是k次买入,和k次卖出的集合,可以用j表示第几次买或卖,即arr[j]=[buy,sell]
  • price表示第i天的价格,buysell分别表示第j次的买卖收入,可以得出下面的公式:
    • j=0时。arr[0]=[Math.max(buy,-price),Math.max(sell,buy+price)]
    • j>0时。第j次的买的价格,是上一次卖的价格减掉当日的价格;第j次的卖的收入,是本次卖的收入加上当日的价格。即:arr[j]=[Math.max(buy,arr[j-1][1]-price),Math.max(sell,arr[j][0]+price)]
  • 具体代码如下
var maxProfit = function(k, prices) {
    var arr = new Array(k);
    for(var j = 0;j<k;j++){
        arr[j] = [-prices[0],0];
    }
    for(var i = 1;i<prices.length;i++){
        var price = prices[i];
        var buy = arr[0][0],sell = arr[0][1];
        arr[0] = [Math.max(buy,-price),Math.max(sell,buy+price)];
        for(var j = 1;j<k;j++){
            buy = arr[j][0],sell = arr[j][1];
            arr[j] = [Math.max(buy,arr[j-1][1] - price),Math.max(sell,arr[j][0] + price)];
       }
    }
    return arr[arr.length-1][1];
};

买卖股票的最佳时机含手续费

  • 本题比上几题,多了手续费,更符合实际交易的场景🐶
  • 因为有手续费,所以有可能存在持有一支股票,等到卖掉时的价钱能够抵掉手续费时才卖掉。
  • 假设sell是卖掉时的收入,buy是买入时的收入。
  • 当日的sellbuy + prices[i] - fee,当日的buysell-prices[i]
  • 因为需要求最大值,所以可以得出下面的公式:
    • sell = Math.max(sell, buy + prices[i] - fee)
    • buy = Math.max(buy, sell - prices[i])
  • 具体代码如下
var maxProfit = function(prices, fee) {
    var buy = -prices[0],sell = 0;
    for(var i = 1;i<prices.length;i++){
        sell = Math.max(sell, buy + prices[i] - fee);
        buy = Math.max(buy, sell - prices[i]);
    }
    return sell;
};

最佳买卖股票时机含冷冻期

  • 本题多了冷冻期的概念,即:卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
  • 假设sell是卖掉时的收入,buy是买入时的收入,freeze是冷冻期的收入。
  • 在冷冻期是不能进行买卖的,所以冷冻期的收入是前一天的卖掉后的收入。
  • 冷冻期过后,才能进行买卖,所以每日卖掉的收入是冷冻期的收入减去当日的价格。
  • 所以可以得出下面的公式:
    • sell = Math.max(sell,buy+prices[i])
    • buy = Math.max(buy,freeze-prices[i])
    • freeze = 前一天卖掉的收入
  • 具体代码如下
var maxProfit = function(prices) {
    var sell = 0,buy = -prices[0],freeze = 0;
    for(var i = 1;i<prices.length;i++){
        var temp = sell;
        sell = Math.max(sell,buy+prices[i]);
        buy = Math.max(buy,freeze-prices[i]);
        freeze = temp;
    }
    return sell;
};

总结

  • 根据买卖股票的题目要求,确定各种状态,如果买入时的收入卖掉时的收入等。
  • 确定各种状态之间的关系,得出相应的公式。
  • 根据公式实现具体的代码。