贪心—leetcode每日一题—122.买卖股票的zuijia时机

461 篇文章 1 订阅

题目一:leetcode122.买卖股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
在这里插入图片描述
在这里插入图片描述
思路1:

贪心:只要今天比明天小就买入,然后在第二天卖出。

解答1:

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

思路2:
动态规划:略,见代码解析

解答2:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0
        n=len(prices)
        dp=[[0]*2 for _ in range(n)]
        #dp[i][0]:第i天不持有股票时的利润值
        #dp[i][1]:第i天持有股票时的利润值
        dp[0][0]=0
        dp[0][1]=-prices[0]
        for i in range(1,n):
            #dp[i][0]:昨天未持有 or 昨天持有今天卖掉
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i])
            #dp[i][1]:昨天就持有 or 昨天未持有今天买入
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
        return dp[n-1][0]

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

解答:
方法一:

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        if not prices:
            return 0
        n=len(prices)
        k=min(k,n//2)
        #用buy[i][j] 表示对于数组prices[0..i] 中的价格而言,进行恰好j笔交易,并且当前手上持有一支股票,这种情况下的最大利润;
        #用sell[i][j] 表示对于数组prices[0..i] 中的价格而言,恰好进行j笔交易,并且当前手上不持有股票,这种情况下的最大利润。
        buy=[[0]*(k+1) for _ in range(n)]
        sell=[[0]*(k+1) for _ in range(n)]
        buy[0][0],sell[0][0]=-prices[0],0
        
        #对利润值进行初始化,将其设为最小
        for i in range(1, k + 1):
            buy[0][i] = sell[0][i] = float("-inf")

        for i in range(1, n):
            #buy[i][0]:i-1持有但目前还未卖出,i-1不持有且在i买入
            buy[i][0] = max(buy[i - 1][0], sell[i - 1][0] - prices[i])
            for j in range(1, k + 1):
                #对于buy[i][j],我们考虑当前手上持有的股票是否是在第i天买入的
                buy[i][j] = max(buy[i - 1][j], sell[i - 1][j] - prices[i])
                #对于sell[i][j],我们考虑股票是否是在第i天卖出的
                sell[i][j] = max(sell[i - 1][j], buy[i - 1][j - 1] + prices[i]);  

        return max(sell[n - 1])

方法二:

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n=len(prices)
        if n==0:
            return 0
        #dp[i][j]:j为奇数代表买入,j为偶数代表卖出,j有2k+1种状态
        dp=[[0]*(2*k+1) for _ in range(n)]
        
        #初始化
        for j in range(1,2*k,2):
            dp[0][j]=-prices[0]
        
        #状态转移
        for i in range(1,n):
            for j in range(0,2*k,2):
                dp[i][j+1]=max(dp[i-1][j+1],dp[i-1][j]-prices[i])
                dp[i][j+2]=max(dp[i-1][j+2],dp[i-1][j+1]+prices[i])
        return dp[n-1][2*k]

方法三:在方法二的基础上做了空间优化

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        n=len(prices)
        if n==0:
            return 0
        #dp[i][j]:j为奇数代表买入,j为偶数代表卖出,j有2k+1种状态
        dp=[0]*(2*k+1)
        
        #初始化
        for j in range(1,2*k,2):
            dp[j]=-prices[0]
        
        #状态转移
        for i in range(1,n):
            for j in range(0,2*k,2):
                dp[j+1]=max(dp[j+1],dp[j]-prices[i])
                dp[j+2]=max(dp[j+2],dp[j+1]+prices[i])
        return dp[2*k]

题目三:leetcode123.买卖股票的最佳时机III
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
在这里插入图片描述
在这里插入图片描述

思路:
因为最多只允许进行两次交易,所以每一天的状态只有5种,即:
1.没有进行任何交易
2.只进行过一次买操作
3.完成一笔交易
4.在完成了一次交易后,又进行了一次买操作
5.完成两笔交易

那么对于边界条件,我们考虑第 i=0 天时的四个状态:
1.以prices[0] 的价格买入股票,因此buy1=-prince[0] ;
2.即为在同一天买入并且卖出,因此sell1=0;
3.在同一天买入并且卖出后再以prices[0] 的价格买入股票,因此buy2 =−prices[0];
4.同理可得sell2 =0

解答:

方法一:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        n = len(prices)
        #buy1:只进行过一次买操作的最大利润
        #buy2:在完成了一次交易后,又进行了一次买操作的最大利润
        buy1 = buy2 = -prices[0]
        #sell1:完成一笔交易时的最大利润
        #sell2:完成两笔交易时的最大利润
        sell1 = sell2 = 0
        for i in range(1, n):
            buy1 = max(buy1, -prices[i])
            sell1 = max(sell1, buy1 + prices[i])
            buy2 = max(buy2, sell1 - prices[i])
            sell2 = max(sell2, buy2 + prices[i])
        return sell2

方法二:

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #0:无操作
        #1:第一次买入
        #2:第一次卖出
        #3:第二次买入
        #4:第二次卖出
        n=len(prices)
        dp=[[0]*5 for _ in range(n)]
        dp[0][1]=-prices[0]
        dp[0][3]=-prices[0]
        for i in range(1,n):
            dp[i][0]=dp[i-1][0]
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i])
            dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i])
            dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i])
            dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i])
        return dp[n-1][4]
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #动态规划
        n=len(prices)
        #dp[i][j]:第i天为状态j时的最大利润
        #j=0:没有操作
        #j=1:第一次持有
        #j=2:第一次不持有
        #j=3:第二次持有
        #j=4:第二次不持有
        dp=[0]*5
        dp[0][1]=-prices[0]
        dp[0][3]=-prices[0]
        res=0
        for i in range(1,n):
            #第i天没有操作,前一天也必然没有操作
            dp[i][0]=dp[i-1][0]
            #第i天第一次持有股票的最大利润
            dp[i][1]=max(dp[i-1][1],-prices[i])
            dp[i][2]=max(dp[i-1][2],dp[i][1]+prices[i])
            ##第i天第二次持有股票的最大利润
            dp[i][3]=max(dp[i-1][3],dp[i][2]-prices[i])
            dp[i][4]=max(dp[i-1][4],dp[i][3]+prices[i])
        return dp[n-1][4]

方法三:空间优化

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #0:无操作
        #1:第一次买入
        #2:第一次卖出
        #3:第二次买入
        #4:第二次卖出
        n=len(prices)
        dp=[0]*5
        dp[1]=-prices[0]
        dp[3]=-prices[0]
        for i in range(1,n):
            dp[0]=dp[0]
            dp[1]=max(dp[1],dp[0]-prices[i])
            dp[2]=max(dp[2],dp[1]+prices[i])
            dp[3]=max(dp[3],dp[2]-prices[i])
            dp[4]=max(dp[4],dp[3]+prices[i])
        return dp[4]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值