lintcode393买卖股票的最佳时机IV

本文介绍了一种基于动态规划的方法来解决给定股票价格和交易次数限制下的最大利润问题。当交易次数达到一定阈值时,算法简化为寻找连续上升的价格区间以累积利润。

描述

给定n天的股票值和允许的最大交易次数k,问最大利润。
已经买了一只股必须要卖出去才能买下一支股。

思路

dp。
当k>=n//2时,达到n天交易次数的饱和,这时,只要一有利润就会有收入。具体在实现上,相邻两天如果是股票值上升的,就记入利润。
其余情况,用dp。首先考虑状态,本题有两个,第几天和第几次交易。
dp[i][j]dp[i][j]dp[i][j]代表前iii天最多jjj次交易完成后的最大利润。
状态转移方程:
dp[i][j]=max(dp[i−1][j],dp[m][j−1]+p[i]−p[m]),m=0,....,i−1dp[i][j]=max(dp[i-1][j], dp[m][j-1]+p[i]-p[m]),m=0,....,i-1dp[i][j]=max(dp[i1][j],dp[m][j1]+p[i]p[m]),m=0,....,i1
mmm代表最多j−1j-1j1次交易买入的时间是第mmm天。
于是有了下面的代码:

from typing import (
    List,
)

class Solution:
    """
    @param K: An integer
    @param prices: An integer array
    @return: Maximum profit
    """
    def maxProfit(self, K, prices):
        k = K
        n = len(prices)
        if k==0 or n==0:
            return 0
        if k >= n//2:
            res = 0
            for i in range(1, n):
                if prices[i]-prices[i-1]>0:
                    res += prices[i]-prices[i-1]
            return res
        else:
            dp = [[0]*(k+3) for i in range(n+3)]
        
            for i in range(1, n):
                for j in range(1, k+1):
                    diff = max([dp[k][j-1]-prices[k] for k in range(i)])
                    dp[i][j] = max(diff+prices[i], dp[i-1][j])
                    
            return dp[n-1][k]

这个代码运行超时,因为时间复杂度O(nnk),主要是求diff用了O(n)。可以优化一下。
diff实际上是 dp[m][j−1]−p[m],m=0,...i−1dp[m][j-1]-p[m],m=0,...i-1dp[m][j1]p[m]m=0,...i1,j-1是不动的,m是动的,可以把j-1代表的循环放外层,m
代表的循环放内层,每次循环的时候记录一下,就不需要额外的O(n)。具体是,dp[i][j]dp[i][j]dp[i][j]的i和j的含义换一下,i代表最多i次交易,j代表前j天。于是有:

from typing import (
    List,
)

class Solution:
    """
    @param K: An integer
    @param prices: An integer array
    @return: Maximum profit
    """
    def maxProfit(self, K, prices):
        k = K
        n = len(prices)
        if k==0 or n==0:
            return 0
        if k >= n//2:
            res = 0
            for i in range(1, n):
                if prices[i]-prices[i-1]>0:
                    res += prices[i]-prices[i-1]
            return res
        else:
            dp = [[0]*(n+3) for i in range(k+3)]
        
            for i in range(1, k+1):
                diff = float('-inf')
                for j in range(1, n):
                    diff = max(diff, dp[i-1][j-1]-prices[j-1])
                    dp[i][j] = max(diff+prices[j], dp[i][j-1])
                    
            return dp[k][n-1]

通过。注意diff初始化,不能初始化为0,要初始化为float(‘-inf’)代表负无穷。
目标是要求最大的diff,所以初始化为最小值。
因为diff代表第i-1次交易前j-1天的最大利润,利润可以为负的,代表亏损,
如果初始化为0,就可能比实际利润要大,显然不合理。
当初始化为最小或最大的值的时候要考虑当下的题目的实际情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值