股票问题

对于股票问题,本质上只有两个维度在变,分别是天数和那一天的状态

121. 买卖股票的最佳时机

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

func maxProfit(prices []int) int {
    size := len(prices)
    dp := make([][]int, 2)
    for i := range dp {
        dp[i] = make([]int, 2)
    }

    dp[0][0] = -prices[0]
    dp[0][1] = 0

    for i := 1; i < size; i++ {
        dp[i % 2][0] = max(dp[(i-1)%2][0], -prices[i])
        dp[i % 2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0]+prices[i])
    }

    return dp[(size-1)%2][1]
}

122. 买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II

给定一个数组 prices ,其中 prices[i] 表示股票第 i 天的价格。 在每一天,你可能会决定购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以购买它,然后在 同一天 出售。返回 你能获得的 最大 利润 。

func maxProfit(prices []int) int {
    size := len(prices)
    dp := make([][]int, 2)
    for i := range dp {
        dp[i] = make([]int, 2)
    }

    dp[0][0] = -prices[0]
    dp[0][1] = 0

    for i := 1; i < size; i++ {
        dp[i % 2][0] = max(dp[(i-1)%2][0], dp[(i-1)%2][1] - prices[i])
        dp[i % 2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0] + prices[i])
    }

    return dp[(size-1)%2][1]
}

123. 买卖股票的最佳时机 III

123. 买卖股票的最佳时机 III

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

func maxProfit(prices []int) int {
    size := len(prices)
    dp := make([][]int, 5)
    for i := range dp {
        dp[i] = make([]int, 5)
    }
    // dp[i][j] j有5个状态,0没有操作,1第一次买入,2第一次卖出,3第二次买入,4第二次卖出
    dp[0][1] = -prices[0]
    dp[0][3] = -prices[0]

    for i := 1; i < size; i++ {
        dp[i%5][0] = dp[(i-1)%5][0]
        dp[i%5][1] = max(dp[(i-1)%5][0] - prices[i], dp[(i-1)%5][1])
        dp[i%5][2] = max(dp[(i-1)%5][1] + prices[i], dp[(i-1)%5][2])
        dp[i%5][3] = max(dp[(i-1)%5][2] - prices[i], dp[(i-1)%5][3])
        dp[i%5][4] = max(dp[(i-1)%5][3] + prices[i], dp[(i-1)%5][4])
    }

    return dp[(size-1)%5][4]
}

188. 买卖股票的最佳时机 IV

188. 买卖股票的最佳时机 IV

给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

func maxProfit(k int, prices []int) int {
    if len(prices) == 0 {
        return 0
    }
    
    size := len(prices)
    dp := make([][]int, size)
    for i := range dp {
        dp[i] = make([]int, 2 * k + 1)
    }
    // dp[i][j] j有5个状态,0没有操作,1第一次买入,2第一次卖出,...2k-1次买入,2k次卖出
    // basecase偶数位都为0,奇数为-prices[0]
    for j := 1; j < 2 * k + 1; j+=2 {
        dp[0][j] = -prices[0]
    }

    for i := 1; i < size; i++ {
        for j := 0; j < 2 * k - 1; j+=2 {
            dp[i][j+1] = max(dp[i-1][j] - prices[i], dp[i-1][j+1])
            dp[i][j+2] = max(dp[i-1][j+1] + prices[i], dp[i-1][j+2])
        }
    }

    return dp[size-1][2*k]
}

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

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

给定一个整数数组prices,其中第  prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)

func maxProfit(prices []int) int {
    size := len(prices)
    if size == 0 {
        return 0
    }

    dp := make([][]int, size)
    for i := range dp {
        dp[i] = make([]int, 4)
    }
    // 状态有,0买入状态,1之前卖出,2刚卖出,3处于冷冻期
    dp[0][0] = -prices[0]
    for i := 1; i < size; i++ {
        dp[i][0] = max(dp[i-1][0], max(dp[i-1][3], dp[i-1][1]) - prices[i])
        dp[i][1] = max(dp[i-1][1], dp[i-1][3]) // 冷冻期只有一天,到今天就不是冷冻期了
        dp[i][2] = dp[i-1][0] + prices[i]
        dp[i][3] = dp[i-1][2]
    }
    return max(max(dp[size-1][1], dp[size-1][2]), dp[size-1][3])
}

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

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

给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。 你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。 返回获得利润的最大值。 注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

func maxProfit(prices []int, fee int) int {
    size := len(prices)
    dp := make([][]int, 2)
    for i := range dp {
        dp[i] = make([]int, 2)
    }

    dp[0][0] = -prices[0]
    dp[0][1] = 0

    for i := 1; i < size; i++ {
        dp[i % 2][0] = max(dp[(i-1)%2][0], dp[(i-1)%2][1] - prices[i])
        dp[i % 2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0] + prices[i] - fee)
    }

    return dp[(size-1)%2][1]
}