LintCode-买卖股票的最佳时机I、II、III

思路概述

I、只许购买一次股票。遍历所有时间的股票价格,以当前股票价格之前出现过的最低价作为买入价,并计算出当天价格出售的收益,与曾经的最大收益对比,遍历完即可的得到最大可能收益;
II、交易次数不限,但每次只能持有一只股票。就可以用贪心法,只要当天价格高于前一天,就加入到收益之中去;
III、最多两次购买股票。动态规划问题,可以以第i天未分界点,计算前面的单次股票最大收益和后面股票的最大收益,然后求两者和的最大值作为最终的收益。
IV、特殊的动态规划问题,Local[i][j]表示在到达第i天时最多可进行j次交易并且最后一次交易在最后一天卖出的最大利润,此为局部最优。Global[i][j]为在到达第i天时最多可进行j次交易的最大利润,此为全局最优。特别注意,递推公式的max函数实际上代表了对过去状态产生的多个结果进行择优。

特殊动态规划问题公式

Local[i][j] = max(Local[i-1][j], Global[i-1][j-1]) + difference(状态增益值)
Global[i][j] = max(Local[i][j], Global[i-1][j])
理解公式很重要。

I

描述

假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格。如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润。

样例

给出一个数组样例 [3,2,3,1,2], 返回 1

代码

class Solution:
    """
    @param prices: Given an integer array
    @return: Maximum profit
    """
    def maxProfit(self, prices):
        maxProfit = 0
        if len(prices) == 0:
            return maxProfit
        minPrice = prices[0]
        for i in range(1, len(prices)):
            minPrice = min(minPrice, prices[i])
            maxProfit = max(maxProfit, prices[i]-minPrice)
        return maxProfit

II

描述

假设有一个数组,它的第i个元素是一个给定的股票在第i天的价格。设计一个算法来找到最大的利润。你可以完成尽可能多的交易(多次买卖股票)。然而,你不能同时参与多个交易(你必须在再次购买前出售股票)。

样例

给出一个数组样例[2,1,2,0,1], 返回 2

代码

class Solution:
    """
    @param prices: Given an integer array
    @return: Maximum profit
    """
    def maxProfit(self, prices):
        # write your code here
        maxProfit = 0
        if len(prices) == 0:
            return maxProfit
        for i in range(1, len(prices)):
            maxProfit = maxProfit + max(0, prices[i]-prices[i-1])
        return maxProfit

III

描述

假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。设计一个算法来找到最大的利润。你最多可以完成两笔交易。

样例

给出一个样例数组 [4,4,6,1,1,4,2,5], 返回 6

代码

class Solution:
    """
    @param prices: Given an integer array
    @return: Maximum profit
    """
    def maxProfit(self, prices):
        # write your code here
        if len(prices) <= 1:
            return 0
        ProfitLift = [0 for i in range(len(prices))]
        ProfitRight = [0 for i in range(len(prices))]
        minPrice = prices[0]
        for i in range(1, len(ProfitLift)):
            minPrice = min(minPrice, prices[i])
            ProfitLift[i] = max(ProfitLift[i-1], max(ProfitLift[i], prices[i]-minPrice))
        maxPrice = prices[-1]
        for i in reversed(range(1, len(ProfitRight))):
            maxPrice = max(maxPrice, prices[i])
            ProfitRight[i-1] = max(ProfitRight[i], max(ProfitRight[i-1], maxPrice-prices[i-1]))
        result = 0
        for i in range(0, len(prices)):
            result = max(result, ProfitLift[i] + ProfitRight[i])
        return result        

IV

描述

假设你有一个数组,它的第i个元素是一支给定的股票在第i天的价格。
设计一个算法来找到最大的利润。你最多可以完成 k 笔交易。

样例

给定价格 = [4,4,6,1,1,4,2,5], 且 k = 2, 返回 6.

挑战

O(nk) 时间序列。

代码

class Solution:
    """
    @param nums: A list of integers
    @param k: An integer denote to find k non-overlapping subarrays
    @return: An integer denote the sum of max k non-overlapping subarrays
    """
    def maxProfit(self, K, prices):
        # write your code here
        if len(prices) <=1:
            return 0
        elif K >= len(prices):
            result = 0
            for i in range(1, len(prices)):
                result = max(prices[i]-prices[i-1], 0) + result
            return result
        else:
            Local = [[0 for i in range(K + 1)] for i in range(len(prices) + 1)]
            Global = [[0 for i in range(K + 1)] for i in range(len(prices) + 1)]
    
            for i in range(1, len(prices)+1):
                for j in range(1, K+1):
                    if j*2 > i:
                        Local[i][j] = 0
                        Global[i][j] = 0
                    else:
                        Local[i][j] = max(Local[i-1][j], Global[i-1][j-1]) + (prices[i-1] - prices[i-2])
                        Global[i][j] = max(Local[i][j], Global[i-1][j])
            return max(Global[-1])

(优化空间使用)

class Solution:
    """
    @param K: An integer
    @param prices: An integer array
    @return: Maximum profit
    """
    def maxProfit(self, K, prices):
        # write your code here
        if len(prices) <=1:
            return 0
        elif K >= len(prices):
            result = 0
            for i in range(1, len(prices)):
                result = max(prices[i]-prices[i-1], 0) + result
            return result
        else:
            Local = [[0 for j in range(K+1)] for i in range(2)]
            Global = [[0 for j in range(K+1)] for i in range(2)]
            
            for i in range(1, len(prices)+1):
                for j in range(1, K+1):
                    if j*2 >i:
                        Local[1][j] = 0
                        Global[1][j] = 0
                    else:
                        Local[1][j] = max(Local[0][j], Global[0][j-1]) + (prices[i-1] - prices[i-2])
                        Global[1][j] = max(Local[1][j], Global[0][j])
                for j in range(1, K+1):
                    Local[0][j] = Local[1][j]
                    Global[0][j] = Global[1][j]
            return max(Global[0])

题目来源

https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-i/description
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-ii/description
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-iii/description
https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-iv/description

你可能感兴趣的:(LintCode-买卖股票的最佳时机I、II、III)