代码随想录算法训练营第四期第四十九天 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

121. 买卖股票的最佳时机

# 给定一个数组 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。
class Solution:
    # 1. 确定dp数组(dp table)以及下标的含义
    # dp[i][0]表示第i天持有股票所得最多现金
    # dp[i][1]表示第i天不持有股票所得最多现金
    def maxProfit(self, prices: [int]) -> int:
        if len(prices) == 1:
            return 0
        dp = [[0 for _ in range(2)] for _ in range(len(prices))]
        dp[0][0] = -prices[0] # 第一天就买入股票,花了钱,所以余额为负数
        dp[1][0] = 0 # 第一天就不买股票
        for i in range(1, len(prices)):
            dp[i][0] = max(dp[i-1][0], -prices[i]) # 取最便宜的股票
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]) # 在不买和买之间权衡
        return dp[-1][1] # 最后一个肯定是最大的

    def maxProfit1(self, prices: [int]) -> int: # 滚动数组的写法
        # 还没有细看
        if len(prices) == 1:
            return 0
        dp = [[0] * 2 for _ in range(2)] # 注意这里只开辟了一个2 * 2大小的二维数组
        dp[0][0] = -prices[0]
        dp[1][0] = 0
        for i in range(1, len(prices)):
            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[(len(prices)-1) % 2][1]

    def maxProfit2(self, prices: [int]) -> int:
        # 看起来是动态规划,其实是贪心的写法,这里dp也不用设置为数组,设置为一个int即可
        mi = prices[0]
        dp = [0 for _ in range(len(prices))]
        dp[0] = 0
        for i in range(1, len(prices)):
            mi = min(mi, prices[i])
            dp[i] = max(dp[i - 1], prices[i] - mi)
        return dp[-1]

    def maxProfit3(self, prices: [int]) -> int:
        # 这里是随想录中的python贪心写法
        mi = prices[0]
        dp = 0
        for i in range(1, len(prices)):
            mi = min(mi, prices[i])
            dp = max(dp, prices[i] - mi)
        return dp

if __name__ == '__main__':
    prices = [7,1,5,3,6,4]
    prices = [1]
    # dp = [[0 for _ in range(2)] for _ in range(len(prices))]
    # print(dp)
    # prices = [7, 6, 4, 3, 1]
    tmp = Solution()
    res = tmp.maxProfit2(prices)
    print(res)

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

# 给你一个整数数组prices ,其中prices[i]表示某支股票第i天的价格。
# 在每一天,你可以决定是否购买和 / 或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后在同一天出售。返回你能获得的最大利润 。
#
# 示例1:
# 输入:prices = [7, 1, 5, 3, 6, 4]
# 输出:7
# 解释:在第2天(股票价格 = 1)的时候买入,在第3天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
# 随后,在第4天(股票价格 = 3)的时候买入,在第5天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
# 总利润为4 + 3 = 7 。
#
# 示例2:
# 输入:prices = [1, 2, 3, 4, 5]
# 输出:4
# 解释:在第1天(股票价格 = 1)的时候买入,在第5天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。总利润为4 。
#
# 示例3:
# 输入:prices = [7, 6, 4, 3, 1]
# 输出:0
# 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为0 。
class Solution:
    def maxProfit(self, prices: [int]) -> int:
        if len(prices) == 1:
            return 0
        dp = [[0 for _ in range(2)] for _ in range(len(prices))]
        dp[0][0] = -prices[0]
        dp[1][0] = 0
        for i in range(1, len(prices)):
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]) #注意这里是和121. 买卖股票的最佳时机唯一不同的地方
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i])
        return dp[-1][1]  # 最后一个肯定是最大的
    
    # 这个之前用贪心的思路做过,有印象
    def maxProfit2(self, prices: [int]) -> int:
        res = 0
        for i in range(1,len(prices)):
            if prices[i] > prices[i-1]:
                res += prices[i] - prices[i-1]
        return res


if __name__ == '__main__':
    price = [7,1,5,3,6,4]
    tmp = Solution()
    res = tmp.maxProfit(price)
    res = tmp.maxProfit2(price)
    print(res)

你可能感兴趣的:(算法,动态规划,leetcode)