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

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。

注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入: [2,4,1], k = 2
输出: 2
解释: 在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:

输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
     随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。

这个题是122题的拓展。这里限定了交易次数k。我参考了Code_Ganker的解题思路。
下面说一下个人理解:
这里维护了两个变量:

  • global[i][j]:是指在到达i天时,最多进行j次交易获得的最大利润。
  • local[i][j]:是指到达i天时,最多可以进行j次交易。而且最后一次交易是在i天卖出的获得最大利润。
    下面是维护两个变量的递归式:
    g l o b a l [ i ] [ j ] = m a x ( g l o b a l [ i − 1 ] [ j ] , l o c a l [ i ] [ j ] ) global[i][j] = max(global[i-1][j],local[i][j]) global[i][j]=max(global[i1][j],local[i][j])
    这个公式很好理解,因为如果最后一次交易卖出的时间不是第i天,那么到达第i天获得的最大利润一定等于到达第i-1天获得的最大利润。
    l o c a l [ i ] [ j ] = m a x ( g l o b a l [ i − 1 ] [ j − 1 ] + m a x ( d i f f , 0 ) , l o c a l [ i − 1 ] [ j ] + d i f f ) local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j] + diff) local[i][j]=max(global[i1][j1]+max(diff,0),local[i1][j]+diff)
    global[i-1][j-1]表示在到达i-1天,一共进行了j-1次交易。加上max(diff,0)。如果j - (j-1)是赚钱的,就加上这次交易。如果不赚钱,那么就在第j天,当天买,当天卖。这样最后一次交易收益为0.
    local[i-1][j]表示在到达第i-1天,一共进行了j次交易。从local[i][j-1]到local[i][j]。只需要在local[i][j-1]加上最有一次交易。就满足了最后一次交易是在第i天卖出的条件。

给出了递归式,就可以写程序了。

  • 还需要注意 一种情况,如果可以交易的次数k超过了数组的长度。这个问题就可以变成一个无限次数操作的求最大股票利润的,参考买卖股票的最佳时机ll 的思路。

首先给出一个解题方法:

class Solution(object):
    def maxProfit(self, k, prices):
        def solvemaxProfit(prices):
            res = 0
            for i in range(1,length):
                if prices[i] - prices[i-1] >0:
                    res += prices[i] - prices[i-1]
            return res
        if len(prices) <= 1:
            return 0
        length = len(prices)
        if k >= length:
            return solvemaxProfit(prices)
        l = [[0]*(k+1) for i in range(length)]
        g = [[0]*(k+1) for i in range(length)]
        for i in range(length-1):
            diff = prices[i+1] - prices[i]
            for j in range(1,k+1):
                l[i+1][j] = max(g[i][j-1] + max(diff,0),l[i][j] + diff)
                g[i+1][j] = max(g[i][j],l[i+1][j])
        return g[-1][-1]

可以将local矩阵和global矩阵降维。使用循环赋值这样可以节省空间开支。

  • 此时要注意为保证循环赋值的正确性,内循环0-k必须采用到过来循环的操作。
class Solution(object):
    def maxProfit(self, k, prices):
        """
        :type k: int
        :type prices: List[int]
        :rtype: int
        """
        def solvemaxProfit(prices):
            res = 0
            for i in range(1,length):
                if prices[i] - prices[i-1] >0:
                    res += prices[i] - prices[i-1]
            return res
        if len(prices) <= 1:
            return 0
        length = len(prices)
        if k >= length:
            return solvemaxProfit(prices)
        l = [0]*(k+1)
        g = [0]*(k+1)
        for i in range(length-1):
            diff = prices[i+1] - prices[i]
            for j in range(k,0,-1):
                l[j] = max(g[j-1] + max(diff, 0),l[j]+diff)
                g[j] = max(g[j], l[j]) 
        return g[k]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值