Best Time to Buy and Sell Stock III

解题思路来自:https://blog.csdn.net/u012501459/article/details/46514309
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 (ie, you must sell the stock before you buy again).

即是每天的股票价格,交易两次,问最大收益。
解法1:
这个问题可以转换成Best Time to Buy and Sell Stock I问题。

两次股票交易的核心是可以定义一个交易点,在这个交易点之前可以做一次交易(赚的最大数目的钱为firstProf),在这个交易点之后可以做一个交易(赚的最大数目的钱是secondProf)。那么要求的是max(firstProf+secondProf)。但是这个方法的时间复杂度是O(N^2),空间复杂度是O(1)。leetcode中显示超时。

可以使用两次扫描的方法避免上面的双重循环。

不同于Best Time to Buy and Sell Stock I中定义的初始状态A[i]表示第i天卖出挣的最大数目的钱,这个更进一步直接定义A[i]表示前i天赚的最大数目的钱。minPrice表示从第0天到第i-1天中的最低价格。
A[0]=0。(初始状态)
A[1]=max(prices[1]-prices[0],A[0])
A[2]=max(prices[2]-minPrice,A[1])
…..
即A[i]=max(price[i]-minPrice,A[i-1]).
A[0]=0
另外一次扫描从数组后向前扫描,定义B[i]表示从第i天到最后一天n能赚的最大数目的钱。maxPrice表示第i+1天到n天的最高价格。
B[n]=0。(初始状态)

B[n-1]=max(maxPrice-prices[n-1],B[n])
B[n-2]=max(maxPrice-prices[n-2],B[n-1])
…..
即B[i]=max(maxPrice-prices[i],B[i+1])
B[n]=0
那么以第i天为分割点能赚的最多数目的钱为A[i]+B[i]

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


__author__ = 'Zhang Shuai'


class Solution:
    def maxProfit(self, prices):
        if not prices:
            return 0
        #最大价格差
        pre_maxPrices = 0
        #价格最小值
        minPrice = prices[0]
        #A[0]为0
        A = [pre_maxPrices]

        for i in prices[1:]:
            if i < minPrice:
                minPrice = i
                A.append(A[-1])
            else:
                A.append(max(i-minPrice,A[-1]))
        post_maxPrices = 0
        maxPrices = prices[-1]
        #B[-1]为0
        #B记录的是从当前位置到末尾的最大价格差
        B = [post_maxPrices]
        #从倒数第二位开始循环到0
        for i in prices[-2::-1]:
            if i > maxPrices:
                maxPrices = i
                #因为从后往前,所以每次在index=0插入
                #因为当前位置比之后的最大值还要大,所以不可能在此买入,只能在此位置之后买入,所以此处相当于B[N-2]=B[N-1]
                B.insert(0, B[0])
            else:
                B.insert(0,max(maxPrices-i,B[0]))
        return max([A[i] + B[i] for i in range(len(prices))])
print(Solution().maxProfit([1,2,3,4,5]))

解题思路2:
这个比较厉害,就不写python代码了,了解一下就行了。
在Discuss中看到一种很棒的解法,代码只有10行左右,但是不是很好理解。

第二种解法的核心是假设手上最开始只有0元钱,那么如果买入股票的价格为price,手上的钱需要减去这个price,如果卖出股票的价格为price,手上的钱需要加上这个price。

它定义了4个状态:

Buy1[i]表示前i天做第一笔交易买入股票后剩下的最多的钱;

Sell1[i]表示前i天做第一笔交易卖出股票后剩下的最多的钱;

Buy2[i]表示前i天做第二笔交易买入股票后剩下的最多的钱;

Sell2[i]表示前i天做第二笔交易卖出股票后剩下的最多的钱;

那么Sell2[i]=max{Sell2[i-1],Buy2[i-1]+prices[i]}

   Buy2[i]=max{Buy2[i-1],Sell[i-1]-prices[i]}

   Sell1[i]=max{Sell[i-1],Buy1[i-1]+prices[i]}

   Buy1[i]=max{Buy[i-1],-prices[i]}

可以发现上面四个状态都是只与前一个状态有关,所以可以不使用数组而是使用变量来存储即可。

class Solution {  
public:  
    int maxProfit(vector<int>& prices) {  
        int buy1=numeric_limits<int>::min();  
        int buy2=numeric_limits<int>::min();  
        int sell1=0;  
        int sell2=0;  
        for(int i=0;i<prices.size();i++)  
        {  
            sell2=max(sell2,buy2+prices[i]);  
            buy2=max(buy2,sell1-prices[i]);  
            sell1=max(sell1,buy1+prices[i]);  
            buy1=max(buy1,-prices[i]);  
        }  
        return sell2;  
    }  

};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值