zoukankan      html  css  js  c++  java
  • 动态规划解决买卖股票问题

    121.买卖股票的最佳时机

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            if not prices: return 0
            n = len(prices)
            dp = [[0,0] for _ in range(n)]
            dp[-1][0] = 0
            dp[-1][1] = - float('inf')
            dp[0][0] = 0
            dp[0][1] = - float('inf')
            for i in range(n):
                dp[i][0] = max(dp[i-1][0],dp[i-1][1]+ prices[i]) 
                dp[i][1] = max(dp[i-1][1],- prices[i])
            return dp[-1][0]
    

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

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            if not prices: return 0
            n = len(prices)
            dp = [[0,0] for _ in range(n)]
            dp[-1][0] = 0
            dp[-1][1] = - float('inf')
            dp[0][0] = 0
            dp[0][1] = - float('inf')
            for i in range(n):
                dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i])
                dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])
            return dp[-1][0]
    

    贪心法:用一个变量profit记录利润,只要利润不为负,在当前卖出的话始终是可以盈利的。代码如下:

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            profit = 0
            max_profit = 0
            n = len(prices)
            for i in range(1, n):
                profit = prices[i] - prices[i - 1]
                if profit > 0:
                    max_profit += profit
            return max_profit

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

    给定一个数组,它的第 i 个元素是一支给定的股票在第 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔交易

    思路:

    1.首先定义一个状态方程,用一个三维的dp,dp[i][j][0] 今天是第i天,进行j次交易了,手上没有股票,dp[i][j][1] 今天是第i天,进行j次交易,手上有股票。
    2.dp是求无论手上有没有股票,最后的最大利润。所以最后如果股票全都卖出去了,肯定能获得最大利润,即dp[-1][j][0]
    3.状态转移方程为:
    dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1] + prices[i])
    dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i])
    dp[i][j][0]表示当前手上没有股票,这样的状态可以由两个状态转移得来:前一天没有股票,即dp[i-1][j][0]和前一天手上有股票,但卖出去了,即dp[i-1][j][1] + prices[i]这里需要+ prices[i]因为卖出股票会有收益,要时刻记住我们dp的内涵是最大收益。同理,dp[i][j][1] 可以由:dp[i-1][j][1]和前一天没有股票但前一天买入了,即dp[i-1][j-1][0] - prices[i]转移。

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            # 2笔
            # 定义卖出股票,交易次数 j + 1
            #dp[i][j][0] 今天是第i天 进行 j次 交易 手上没有股票
            #dp[i][j][1] 今天是第i天 进行 j次 交易 手上有股票
            if not prices: return 0
            n = len(prices)
            dp = [[[0] * 2 for _ in range(3)] for _ in range(n)]
            for k in range(3): #base case i=0
                dp[0][k][0] = 0
                dp[0][k][1] = -prices[0]
            for i in range(1, n):
                for j in range(3):
                    if not j:
                        dp[i][j][0] = dp[i-1][j][0]  # 0 base case j=0
                    else:
                        dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j-1][1] + prices[i]) 
                    dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j][0] - prices[i])   
            return max(dp[-1][0][0], dp[-1][1][0], dp[-1][2][0])

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

    给定一个数组,它的第 i 个元素是一支给定的股票在第 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易

    class Solution:
        def maxProfit(self, k: int, prices: List[int]) -> int:
            if not prices: return 0
            n = len(prices)
            if k >= n//2: #和前面122一致(贪心)
                res = 0
                for i in range(1,n):
                    if prices[i] > prices[i-1]:
                        res += prices[i] - prices[i-1]
                return res
            else:
                dp = [[[0 for i in range(2)]  for _ in range(k+1)] for __ in range(n)]
                for t in range(k+1):
                    dp[-1][t][1] = -float('inf')
                    dp[0][t][1] = -float('inf')
                for i in range(n):
                    for j in range(1,k+1):
                        dp[i][j][1] = max(dp[i-1][j][1],dp[i-1][j-1][0] - prices[i])
                        dp[i][j][0] = max(dp[i-1][j][0],dp[i-1][j][1] + prices[i])
                return dp[-1][-1][0]

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

    给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

    你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

    class Solution:
        def maxProfit(self, prices: List[int]) -> int:
            if not prices: return 0
            if len(prices) == 1: return 0
            n = len(prices)
            dp = [[0 for i in range(2)] for _ in range(n)]
            dp[-1][1] = -float('inf')
            dp[-2][1] = -float('inf')
            dp[0][1] = -float('inf')
            for i in range(n):
                dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i])
                dp[i][1] = max(dp[i-1][1],dp[i-2][0] - prices[i])
            return dp[-1][0]

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

    给定一个整数数组 prices,其中第 i 个元素代表了第 i 天的股票价格 ;非负整数 fee 代表了交易股票的手续费用

    你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

    class Solution:
        def maxProfit(self, prices: List[int], fee: int) -> int:
            if not prices: return 0
            n = len(prices)
            dp =[ [0,0] for _ in range(n)]
            dp[-1][1] = -float('inf')
            dp[0][1] = -float('inf')
            for i in range(n):
                dp[i][0] = max(dp[i-1][0],dp[i-1][1] + prices[i] -fee)
                dp[i][1] = max(dp[i-1][1],dp[i-1][0] - prices[i])
            return dp[-1][0]
    

      

  • 相关阅读:
    进程池,线程池,协程,gevent模块,协程实现单线程服务端与多线程客户端通信,IO模型
    线程相关 GIL queue event 死锁与递归锁 信号量l
    生产者消费者模型 线程相关
    进程的开启方式 进程的join方法 进程间的内存隔离 其他相关方法 守护进程 互斥锁
    udp协议 及相关 利用tcp上传文件 socketserver服务
    socket套接字 tcp协议下的粘包处理
    常用模块的完善 random shutil shevle 三流 logging
    day 29 元类
    Django入门
    MySQL多表查询
  • 原文地址:https://www.cnblogs.com/USTC-ZCC/p/12727413.html
Copyright © 2011-2022 走看看