1. 程式人生 > >【演算法】動態規劃演算法—買賣股票的最佳時機系列(1-4)

【演算法】動態規劃演算法—買賣股票的最佳時機系列(1-4)

買賣股票的最佳時機1:

題目:

假設有一個數組,它的第i個元素是一支給定的股票在第i天的價格。
如果你最多隻允許完成一次交易,設計一個演算法來找出最大利潤。

解法:

該題解法和最大連續子陣列和的解法思路是一樣的。

1、根據股票的利益意義,想要更多利益則值低時買進,值高時賣出。根據提供的股票價格不方便得出股票價格變化,對原資料進行計算:list[i] - list[i-1] = 股票的變化。變化為正時股票增長(存在利益),變化為負時股票為下跌(無利益)。

2、得到股票的變化值列表,即求最大子陣列和,最後得到正解。

程式碼:時間O(n),空間O(1)

def maxProfit1(list):
    # 算出利益比變化列表
    NEW=[]
    for i in range(len(list)-1):
        NEW.append(list[i+1]-list[i])
    # 初始化
    imax = 0
    temp = 0
    # 最大子陣列和計算方式
    for d in NEW:
        if temp + d > 0:
            temp += d
        else:
            temp = 0
        # 獲取當前最大子陣列
        imax = max(temp,imax)
    return imax


買賣股票的最佳時機2:

題目:

用一個數組表示股票每天的價格,陣列的第i個數表示股票在第i天的價格。

交易次數不限,但一次只能交易一支股票,也就是說手上最多隻能持有一支股票,求最大收益。

你可以完成儘可能多的交易(多次買賣股票)。
然而,你不能同時參與多個交易(你必須在再次購買前出售股票)。

解法:

貪心演算法,買賣次數不限,問題就簡單了,只要掙錢就賣出。

程式碼:時間O(n),空間O(1)

def maxProfit_2(prices):
    max_profit = 0
    for i in range(1,len(prices)):
        d = prices[i] - prices[i-1]
        # 值為正即存在利益
        if d > 0 :
            max_profit += d
    return max_profit


買賣股票的最佳時機3:

題目:

假設你有一個數組,其中第i 個元素是第i天給定股票的價格。
設計一個演算法來找到最大的利潤。您最多可以完成兩筆交易。
您不可以同時進行多筆交易(即您必須在再次購買之前出售股票)。

解法:

其實也就是找到兩個最大子陣列和,和第一道題差不多。

先求出第一個最大子陣列,避開第一個最大子陣列的情況下,再求出第二大子陣列,再相加即可。

程式碼1:時間O(n),空間O(1)

def maxProfit_3_1(prices):
    release1 = -999
    release2 = -999
    hold1 = 0
    hold2 = 0
    for i in prices:
        release2 = max (release2, hold2 + i)
        hold2 = max (hold2, release1 - i)
        release1 = max (release1, hold1 + i)
        hold1 = max (hold1, -i)
    return release2

程式碼2:
def maxProfit_3_2(prices):
    sell = [0]
    buy = [0]
    plen = len (prices)
    minp = prices[0]
    maxp = prices[-1]

    for i in range (1, plen):
        minp, maxp = min (minp, prices[i]), max (maxp, prices[plen - i - 1])
        sell.append (max (sell[i - 1], prices[i] - minp))
        buy.append (max (buy[i - 1], maxp - prices[plen - i - 1]))

    return max (sell[i] + buy[plen - i - 1] for i in range (plen))


買賣股票的最佳時機—4:

題目:

假設你有一個數組,它的第i個元素是一支給定的股票在第i天的價格。
設計一個演算法來找到最大的利潤。你最多可以完成 k 筆交易。
你不可以同時參與多筆交易(你必須在再次購買前出售掉之前的股票)

解法:

將這些關鍵變數命名為本地利潤和全域性利潤,以使事情更容易理解

程式碼1:

def maxProfit_4(k,prices):
    if not prices: return 0
    n = len (prices)
    if k >= n // 2:
        return sum (
            x - y
            for x, y in zip (prices[1:], prices[:-1])
            if x > y)

    profits = [0] * n
    for j in range (k):
        max_all = max_prev = max_here = 0
        for i in range (1, n):
            profit = prices[i] - prices[i - 1]
            max_here = max (max_here + profit, max_prev + profit, max_prev)
            max_prev = profits[i]
            profits[i] = max_all = max (max_all, max_here)
    return profits[-1]

程式碼2:

def maxProfit4(self, k, prices):
    n = len(prices)
    if n < 2:
        return 0
    if k >= n / 2:
        return sum(i - j
                   for i, j in zip(prices[1:], prices[:-1]) if i - j > 0)
    globalMax = [[0] * n for _ in xrange(k + 1)]
    for i in xrange(1, k + 1):
        # 最大的利潤與我的交易和賣出股票在第j天。
        localMax = [0] * n
        for j in xrange(1, n):
            profit = prices[j] - prices[j - 1]
            localMax[j] = max(
                # 我們以(i - 1)的交易獲利最多在(j - 1)天
                # 在最後一次交易中,我們每天買進股票(j - 1),然後在第j日賣出。
                globalMax[i - 1][j - 1] + profit,
                # 在(j - 1)天內,我們以(i - 1)的轉換期取得了最大的利潤。
                # 最後一次交易,我們在j日買進股票,在同一天賣出,所以我們有0利潤,顯然我們不需要加它。
                globalMax[i - 1][j - 1],  # + 0,
                # 我們已在(j - 1)天內贏利。
                # 我們想取消那天(j - 1)的銷售,在j日賣出。
                localMax[j - 1] + profit)
            globalMax[i][j] = max(globalMax[i][j - 1], localMax[j])
    return globalMax[k][-1]


有不明白的情況以下連結。

如上案例參考:https://leetcode.com/problemset/all/?search=Best%20Time%20to%20Buy%20and%20Sell%20Stock