算法题--最佳股票交易策略III

image.png

0. 链接

题目链接

1. 题目

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most two transactions.

Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

Example 1:

Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
             Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.

Example 2:

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Example 3:

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

2. 思路1: 动态规划

  • 记录dp[k][i] 表示最多用k次卖出机会, 截止到第i天的最大收益
  • 状态转移方程
dp[k][i] = max(dp[k][i - 1], prices[i] - (prices[j] - dp[k - 1][j - 1]))

含义是在第i天, 可以选择卖出,也可以选择不卖出
- 选择卖出, 则卖出的这笔在第j天买入, 则需要使得第j天的买入累计成本(即包含第j天的买入价, 再扣除之前赚得的利润)最小, 即使得prices[j] - dp[k - 1][j - 1]最小
- 选择不卖出, 则第i天的利润, 跟第i-1天的例如没区别, 即dp[k][i - 1]
最佳利润则要取这两个值的较大值

  • 时间复杂度: ```O(KN)``
  • 空间复杂度: O(KN)

3. 代码

# coding:utf8
from typing import List


class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) == 0:
            return 0

        dp = [[0] * len(prices) for _ in range(3)]
        for k in range(1, 3):
            min_cost = prices[0]
            for i in range(1, len(prices)):
                price = prices[i]
                # 看做第k次交易的最小成本(成本要扣除前面赚的钱)
                min_cost = min(min_cost, price - dp[k - 1][i - 1])
                # 第i天不卖出, 则利润等同于第i-1天的; 若卖出, 则获利price-min_cost
                dp[k][i] = max(dp[k][i - 1], price - min_cost)
        return dp[2][len(prices) - 1]


def my_test(solution, prices):
    print('input: {}; output: {}'.format(prices, solution.maxProfit(prices)))


solution = Solution()
my_test(solution, [3, 3, 5, 0, 0, 3, 1, 4])
my_test(solution, [2, 1, 2, 0, 1])
my_test(solution, [1, 2, 4, 2, 5, 7, 2, 4, 9, 0])

输出结果

input: [3, 3, 5, 0, 0, 3, 1, 4]; output: 6
input: [2, 1, 2, 0, 1]; output: 2
input: [1, 2, 4, 2, 5, 7, 2, 4, 9, 0]; output: 13

4. 结果

image.png

5. 思路2: 简化版动态规划

  • 只有两次交易机会, 则可以通过记录buy1, profit1, buy2, profit2
  • 然后遍历一次数组, 不断最小化buy1和buy2, 同时最大化profit1和profit2, 其中buy2又要扣除之前的累计利润profit1
  • 于是最终获得的profit2就是最大累计利润
  • 时间复杂度 O(KN)
  • 空间复杂度 O(KN)

6. 代码

# coding:utf8
from typing import List


class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) == 0:
            return 0

        buy1 = buy2 = prices[0]
        profit1 = profit2 = 0
        for price in prices:
            buy1 = min(buy1, price)
            profit1 = max(profit1, price - buy1)
            buy2 = min(buy2, price - profit1)
            profit2 = max(profit2, price - buy2)
        return profit2


def my_test(solution, prices):
    print('input: {}; output: {}'.format(prices, solution.maxProfit(prices)))


solution = Solution()
my_test(solution, [3, 3, 5, 0, 0, 3, 1, 4])
my_test(solution, [2, 1, 2, 0, 1])
my_test(solution, [1, 2, 4, 2, 5, 7, 2, 4, 9, 0])


输出结果为

input: [3, 3, 5, 0, 0, 3, 1, 4]; output: 6
input: [2, 1, 2, 0, 1]; output: 2
input: [1, 2, 4, 2, 5, 7, 2, 4, 9, 0]; output: 13

7. 结果

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352