【演算法】動態規劃演算法—買賣股票的最佳時機系列(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