买卖股票的最佳时机

346 阅读2分钟

不管在做任何题目的时候,都要清楚变量的含义

题目内容如下

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

来源:力扣(LeetCode)

整体逻辑

假如我们在有times机会的时候,在第end天可以获得的最大利益mark[times][end]应该如何表达?如果在中间某一天start进行了购买,那么假如在第end天卖出,则获得的收益就如下

mark[times][end] = mark[times-1][start-1] + prices[end] - prices[start] (1 <= start <= end)

要确定最大值,则首先要确定下面表达式的值:

max\{mark[times-1][start-1] - prices[start]\}

需要做的就是从start=1start=end,取得mark[times-1][start-1] - prices[start]的最大值就好了。

细节1

对于每一个mark[times][end]都需要从start=1start=end确定最大值吗?

答案是不需要的,因为如果mark[times][end]值确定了,那么下面表达式的值就是算过的了

pre\_max = max\{mark[times-1][start-1] - prices[start]\}(1<=start<=end)

mark[times][end+1]对应的值其实就是下面的表达式

max\{mark[times-1][start-1] - prices[start]\}(1<=start<=end+1)

相比较mark[times][end],就是多了一个比较的情况end+1,总结来说其实就是下面的表达式

max(pre\_max, mark[times-1][end] - prices[end])

也就是只需要和前一次的比较结果再进行一次比较即可。

细节2

对于每一个mark[times][end]的结果,都是在end进行卖股票,从而获取最大利益吗?

答案是否定的,通过一个简单的例子就可以知道了。比如说在times=1的时候,股价为[1, 3, 2],不应该在第三天进行卖股票的操作,因为第二天卖股票可以获得更大的利益。

整体代码

func maxProfit(prices []int) int {
    length := len(prices)
    if length <= 1 {
        return 0
    }
    mark := make([][]int, 3)
    for idx := 0; idx < 3; idx++ {
        mark[idx] = make([]int, length)
    }

    for llen := 1; llen < 3; llen++ {
        maxPre := -prices[0]
        for end := 1; end < length; end++ {
          	// 细节1
            if tmpMax := mark[llen-1][end-1] - prices[end]; tmpMax > maxPre {
                maxPre = tmpMax
            }
          	// 细节2
            if tmpMax := prices[end] + maxPre; tmpMax > mark[llen][end-1] {
                mark[llen][end] = tmpMax
            } else {
                mark[llen][end] = mark[llen][end-1]
            }
        }
    }

    return mark[2][length - 1]
}