zoukankan      html  css  js  c++  java
  • 151. 买卖股票的最佳时机 III

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

    中文English

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

    样例

    样例 1

    输入 : [4,4,6,1,1,4,2,5]
    输出 : 6
    

    注意事项

    你不可以同时参与多笔交易(你必须在再次购买前出售掉之前的股票)

    思路:

    一.确定状态
    如果要求前n天(第n-1天)结束后,在阶段5的最大获利,设为f[n][5]。 总共就两种可能,要么是第n天刚好处于阶段5,(前一天是阶段4)
    要么是第n天已经处于阶段5,(前一天已经是阶段5)
    情况1:第n-2天就在阶段5 f[n][5]
    情况2:第n-2天还在阶段4 (第二次持有股票) 第n-1天卖掉
    f[n-1][4] + (Pn-1 - Pn-2)

    如果要求前n天(第n-1天)结束后,再阶段4中的最大获利,设为f[n][4]
    情况1:第n-2就在阶段4, f[n-1][4] + (Pn-1 - Pn-2)
    情况2:第n-2天还在阶段3, f[n-1][3] (也可以说是后面加的是0,n天刚刚处于阶段4,获利0,刚刚买了,还没有获利)


    子问题
    要求f[n][1],...f[n][5]
    需要知道f[n-1][1],...,f[n-1][5]
    状态:
    f[i][j]表示前i天(第i-1天)结束后,在阶段j的最大获利

    二.转移方程:

    阶段1,3,5, -- 手中无股票状态
    f[i][j] = max(f[i-1][j],f[i-1][j-1] + Pi-1 - Pi-2)
    昨天已经没有持有股票 昨天仍持有股票,当天刚好卖出股票,所以需要加上当天卖出的股票所获得的利

    解析:
    核心:上一天只有两种可能,要么是已经处于无股票状态,要么是仍然处于股票状态(则当天就需要卖出)

    1.上一天已处于无股票状态:
    f[i][j] = f[i-1][j]
    2.上一天仍处于有股票状态,第i天刚好卖出,处于无股票状态.则获利是上一天的获利f[i-1][j-1] ,加上当天的获利 Pi-1 - Pi-2
    f[i][j] = f[i-1][j-1] + (Pi-1 - Pi-2)
    f[i][j]:前i天(第i-1天)结束后,处于阶段j的最大获利


    阶段2,4 手中有股票状态
    f[i][j] = max(f[i-1][j] + Pi-1 - Pi-2,f[i-1][j-1])

    解析:手中有股票状态f[i][j]
    也只有两种可能:
    1.要么是上一天也持有股票,然后继续获利
    f[i-1][j] + Pi-1 - Pi-2
    2.要么是上一天已经没有股票,然后今天刚好买入,则今天不获利
    f[i-1][j-1]

    三.初始条件和边界情况:
    刚开始(前0天)处于阶段1
    f[0][1] = 0 不获利
    f[0][2] = f[0][3] = f[0][4] =f[0][5] = -无穷

    如果j-1 < 1或者i -2 < 0,对应项不计入max

    注意:f[0][1] 0表示的第多少天,1表示的当前天处于第几阶段

    因为最后买卖两次,所以答案是max(f[i][1],f[i][3],f[i][5)
    最后一天肯定是处于1,3,5这几个阶段,清仓下最后一天最大获利

    四.计算顺序:
    f[0][1]...f[0][5]
    f[1][1]...f[1][5]
    ...
    f[n][1]...f[n][5]

    class Solution:
        """
        @param prices: Given an integer array
        @return: Maximum profit
        """
        '''
        大致思路:
        第i天可能处于5种状态,无股票,有股票,无股票,有股票,无股票
        所以转化为子问题也就是
        如果是第i天处于无股票状态:
        1.上一天也是无股票:f[i-1][j] 
        2.上一天是有股票,第i天刚好无股票(刚好卖出):f[i-1][j-1] + Pi-1 - Pi-2 
        f[i][j] = max(f[i - 1][j],f[i-1][j-1] + Pi-1-Pi-2)
    
        如果是第i天处于有股票状态
        1.上一天处于有股票状态,当天仍然获利 f[i-1][j] + Pi-1 - Pi-2
        2.上一天处于无股票状态,当天刚好买入股票:f[i-1][j] + 0 当天不获利
        f[i][j] = max(f[i-1][j] + Pi-1 - Pi-2,f[i-1][j-1] + 0)
    
    
        '''
        def maxProfit(self, prices):
            if not prices or len(prices) == 0:return 0 
    
            l = len(prices)
            f = [[-sys.maxsize]*6 for _ in range(l + 1)]
            #前0天什么都没有,只能是处于第一阶段,无股票,获利也是0
            f[0][1] = 0
    
            #计算顺序
            for i in range(1,l + 1):
                #如果是处于无股票状态,1,3,5状态
                for j in range(1,6,2):
                    #第一天是不用判断,和上一天判断,后面才需要判断
                    f[i][j] = f[i - 1][j]
                    ##必须保证j > 1,i >= 2,从第二天开始,且必须上一天不能是负无穷。填充的是1,3,5 当天无股票状态
                    if (j > 1) and (i >= 2) and (f[i - 1][j - 1] != -sys.maxsize):#如果上一个是-sys.maxsize 则说明是一个废的值,不符合要求,即不符合该状态(例如第一天第4阶段)
                        f[i][j] = max(f[i][j],f[i - 1][j - 1] + prices[i - 1] - prices[i - 2])
            
                #如果是当天处于有股票状态,2,4状态.填充的是2,4 当前天有股票状态
                for j in range(2,6,2):
                    f[i][j] = f[i - 1][j - 1]
                    if (i >= 2) and (f[i - 1][j - 1] != -sys.maxsize):
                        f[i][j] = max(f[i - 1][j] + prices[i - 1] - prices[i - 2],f[i][j])
            
            return max(f[l][1],f[l][3],f[l][5])
  • 相关阅读:
    ASP.NET 构建高性能网站 架构设计
    ASP.NET 构建高性能网站 架构设计
    Vim和Vi的常用命令
    Vim和Vi的常用命令
    Vim和Vi的常用命令
    【收藏】前端知识体系完整版本
    【收藏】前端知识体系完整版本
    Ubuntu-升级linux软件源,安装vim/五笔
    高阶函数---swift中的泛型介绍(一步步实现Map函数)
    Go基础学习(二)
  • 原文地址:https://www.cnblogs.com/yunxintryyoubest/p/13062817.html
Copyright © 2011-2022 走看看