0
点赞
收藏
分享

微信扫一扫

lintcode393买卖股票的最佳时机IV

爱情锦囊 2022-03-26 阅读 70
动态规划

描述

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

思路

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

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实际上是 d p [ m ] [ j − 1 ] − p [ m ] , m = 0 , . . . i − 1 dp[m][j-1]-p[m],m=0,...i-1 dp[m][j1]p[m]m=0,...i1,j-1是不动的,m是动的,可以把j-1代表的循环放外层,m
代表的循环放内存,每次循环的时候记录一下,就不需要额外的O(n)。具体是, d p [ i ] [ j ] dp[i][j] dp[i][j]的i和j的含义换一下,i代表第几次交易,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,就可能比实际利润要大,显然不合理。
当初始化为最小或最大的值的时候要考虑当下的题目的实际情况。

举报

相关推荐

0 条评论