393. 买卖股票的最佳时机 IV

393. 买卖股票的最佳时机 IV

中文English

给定数组 prices, 其中第 i 个元素代表某只股票在第 i 天第价格.

你最多可以完成 k 笔交易. 问最大的利润是多少?

样例

样例 1:

输入: k = 2, prices = [4, 4, 6, 1, 1, 4, 2 ,5]
输出: 6
解释: 以 4 买入, 以 6 卖出. 然后再以 1 买入, 以 5 卖出. 利润为 2 + 4 = 6.

样例 2:

输入: k = 1, prices = [3, 2, 1]
输出: 0
解释: 不进行交易

挑战

O(nk) 时间复杂度. n 是 prices 数组的大小.

注意事项

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

 
 
输入测试数据 (每行一个参数)如何理解测试数据?
class Solution:
    '''
    大致思路:
    1.如果是K >= len(prices) // 2的话,则说明是可以进行任意次数的交易,直接取每次买卖股票的获得的收益相加即可,全部收益值,和买卖股票II类似
    2.如果 K < len(prices) // 2的话,则说明有k*2 + 1种状态
    和买卖股票III类似
    '''
    def maxProfit(self, K, prices):
        if not prices or len(prices) == 0:return 0

        #第一种情况,如果K >= len(prices) // 2
        max_num = 0
        l = len(prices)
        if (K >= l // 2):
            for i in range(1, l):
                if prices[i] > prices[i - 1]:
                    max_num += prices[i] - prices[i - 1]
            
            return max_num
        
        #第二种情况
        #初始化
        #状态
        s = 2*K + 1 
        f = [[-sys.maxsize]*(s + 1) for _ in range(l + 1)]
        #如果是前0天的话,只有一种可能,处于无股票状态,获利0
        f[0][1] = 0 

        #计算顺序
        for i in range(1,l + 1):
            #处于无股票状态,奇数位
            for j in range(1,s + 1, 2):
                f[i][j] = f[i - 1][j]
                if (i - 2 >= 0) and (f[i - 1][j - 1] != -sys.maxsize):
                    f[i][j] = max(f[i][j],f[i - 1][j - 1] + prices[i - 1] - prices[i - 2])

            #处于有股票状态,偶数位
            for j in range(2,s + 1, 2):
                #上一天刚好无股票,今天刚好买入,不获利
                f[i][j] = f[i - 1][j - 1] + 0
                if (i - 2 >= 0) and (f[i - 1][j] != -sys.maxsize):
                    f[i][j] = max(f[i][j],f[i - 1][j] + prices[i - 1] - prices[i - 2])
        
            #取出最大值即可
            for m in range(1, s + 1,2):
                if f[i][m] > max_num:
                    max_num = f[i][m]
        
        return max_num

#result = Solution().maxProfit(10, [3, 2, 1,4,6,8,9,87,65])
#print(result)

 

优化版本:滚动数组,空间复杂度O(2*(K + 1) * 3) 时间复杂度O(K*len(prices))

##滚动数组 优化版本
class Solution:
    '''
    大致思路:
    1.如果是K >= len(prices) // 2的话,则说明是可以进行任意次数的交易,直接取每次买卖股票的获得的收益相加即可,全部收益值
    2.如果 K < len(prices) // 2的话,则说明有k*2 + 1种状态
    和买卖股票III类似
    '''
    def maxProfit(self, K, prices):
        if not prices or len(prices) == 0:return 0

        #第一种情况,如果K >= len(prices) // 2
        max_num = 0
        l = len(prices)
        if (K >= l // 2):
            for i in range(1, l):
                if prices[i] > prices[i - 1]:
                    max_num += prices[i] - prices[i - 1]
            
            return max_num
        
        #第二种情况
        #初始化
        #状态
        s = 2*K + 1 
        f = [[-sys.maxsize]*(s + 1) for _ in range(3)]
        #如果是前0天的话,只有一种可能,处于无股票状态,获利0
        f[0][1] = 0 

        #计算顺序
        for i in range(1,l + 1):
            index = i%3
            #处于无股票状态,奇数位
            for j in range(1,s + 1, 2):
                f[index][j] = f[index - 1][j]
                if (i - 2 >= 0) and (f[index - 1][j - 1] != -sys.maxsize):
                    f[index][j] = max(f[index][j],f[index - 1][j - 1] + prices[i - 1] - prices[i - 2])

            #处于有股票状态,偶数位
            for j in range(2,s + 1, 2):
                #上一天刚好无股票,今天刚好买入,不获利
                f[index][j] = f[index - 1][j - 1] + 0
                if (i - 2 >= 0) and (f[index - 1][j] != -sys.maxsize):
                    f[index][j] = max(f[index][j],f[index - 1][j] + prices[i - 1] - prices[i - 2])
        
            #取出最大值即可
            for m in range(1, s + 1,2):
                if f[index][m] > max_num:
                    max_num = f[index][m]
        #print(f)
        return max_num

result = Solution().maxProfit(2, [4, 4, 6, 1, 1, 4, 2 ,5])
print(result)

 

 

posted @ 2020-06-08 00:15  风不再来  阅读(93)  评论(0编辑  收藏  举报