算法(24)-股票買賣

股票買賣

  • 1.動態規劃框架
    • LeetCode-121 一次買賣
    • LeetCode-122 不限次數
    • LeetCode-309 不限次數+冷凍期
    • LeetCode-714 不限次數+手續費
    • LeetCode-123 兩次買賣
    • LeetCode-188 k次買賣
  • 2.貪心特解
    • LeetCode-121 一次買賣
    • LeetCode-122 不限次數

解題思路參考buladong解題,詳細信息可以關注該公眾號。

1.動態規劃框架

動態規劃–解決買賣k問題,k取不同的值,團滅:
LeetCode-121 一次買賣
LeetCode-122 不限次數
LeetCode-309 不限次數+冷凍期
LeetCode-714 不限次數+手續費
LeetCode-123 兩次買賣
LeetCode-188 k次買賣

LeetCode-188 k次買賣-給定一個數組,它的第 i 個元素是一支給定的股票在第 i 天的價格。設計一個算法來計算你所能獲取的最大利潤。你最多可以完成 k 筆交易。注意: 你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

利用動態規劃來解決問題,確定每一天有多少可能的狀態,再找出狀態對應的選擇。

每天選擇可能有三種:買入,賣出,無操作。但是,三種選擇的發生是有條件的。(賣出操作的前提是你持有股票)

每天的狀態變量有3個:天數,允許交易的最大次數,當前的持有狀態(持有股票1/未持有0)。三維數組可以裝下所有狀態。
dp[i][k][0or1]dp[i][k][0 or 1]dp[i][k][0or1], 到第i天,最多進行k次,手上持有/未持有股票,獲得的最多利潤。
要求解的是dp[n?1][K][0]dp[n-1][K][0]dp[n?1][K][0]的值。

k 買入算是一次操作,收益一開始是0,一次買賣:買入時0-買入時價格,賣出時:0-買入時價格+賣出時價格

狀態轉移方程:
dp[i][k][0]=max(dp[i?1][k][0],dp[i?1][k][1]+prices[i])dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+prices[i])dp[i][k][0]=max(dp[i?1][k][0],dp[i?1][k][1]+prices[i])
今天未持有:昨天未持有/昨天持有賣掉
dp[i][k][1]=max(dp[i?1][k][1],dp[i?1][k?1][0]?prices[i])dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0]-prices[i])dp[i][k][1]=max(dp[i?1][k][1],dp[i?1][k?1][0]?prices[i])
今天持有:昨天持有/昨天持有賣掉

初始狀態base case:
未開始未持有,收益為0:dp[?1][k][0]=0dp[-1][k][0] = 0dp[?1][k][0]=0
未開始以持有,不可能,收益為負無窮:max 的時候取不到dp[?1][k][1]=?∞dp[-1][k][1] = -\inftydp[?1][k][1]=?
允許的最大交易次數為0,未持有無收益:dp[i][0][0]=0dp[i][0][0] = 0dp[i][0][0]=0
允許的最大交易次數為0,持有不可能設為負無窮:dp[i][0][1]=?∞dp[i][0][1] = -\inftydp[i][0][1]=?

用這個思路來解決 以上的題

LeetCode-121 一次買賣

k =1

# dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][1][1]+prices[i])
# dp[i][1][1] = max(dp[i-1][1][1], dp[i-1][0][0]-prices[i]),dp[i-1][0][0] =0
# k = 1 不可以變,因此上面狀態變量減少為兩個
# dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
# dp[i][1] = max(dp[i-1][1], 0-prices[i]),		dp[i-1][0][0] =0
# dp[i][1]的更新會影響dp[i+1][0]的更新def maxProfit(self, prices):n = len(prices)if n == 0 :return 0dp=[[0,0] for i in range(n)]for i in range(0,n):if i == 0:dp[0][0] = 0dp[0][1] = -prices[0]else:dp[i][0] =  max(dp[i-1][0], dp[i-1][1]+prices[i])dp[i][1] =  max(dp[i-1][1], 0-prices[i])   # dp[i-1][0]未持有收益為0return dp[n-1][0]

LeetCode-122 不限次數

k=∞k = \inftyk=

# dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+prices[i])
# dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0]-prices[i])
# k =  \infty k-1 = k  k 狀態又可以去除
# dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
# dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i]),		dp[i-1][0]為進行了很多次操作用于的收益
# dp[i][1]的更新會影響dp[i+1][0]的更新
def maxProfit(self, prices):n = len(prices)if n == 0:return 0dp = [[0,0] for i in range(n)]for i in range(n):if i == 0:dp[0][0] = 0dp[0][1] = -prices[0]else:dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])return dp[n-1][0]

LeetCode-309 不限次數+冷凍期

賣出股票后,你無法在第二天買入股票 (即冷凍期為 1 天)。

# dp[i][0] = max(dp[i-1][0], dp[i-1][1]+prices[i])
# dp[i][1] = max(dp[i-1][1], dp[i-2][0]-prices[i]),		前兩天賣出操作今天買入    
# 初始值得設定上
def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""n = len(prices)if n == 0:return 0dp = [[0,0] for i in range(n)]for i in range(n):if i == 0:dp[0][0] = 0dp[0][1] = -prices[0]elif i == 1:dp[1][0] = max(dp[0][0], dp[0][1] + prices[1])dp[1][1] = max(dp[0][1], dp[0][0] - prices[1])else:dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])dp[i][1] = max(dp[i-1][1], dp[i-2][0] - prices[i])return dp[n-1][0]

LeetCode-714 不限次數+手續費

給定一個整數數組 prices,其中第 i 個元素代表了第 i 天的股票價格 ;非負整數 fee 代表了交易股票的手續費用。
你可以無限次地完成交易,但是你每筆交易都需要付手續費。如果你已經購買了一個股票,在賣出它之前你就不能再繼續購買股票了。
返回獲得利潤的最大值。
注意:這里的一筆交易指買入持有并賣出股票的整個過程,每筆交易你只需要為支付一次手續費。

每筆交易減去一個手續費即可,在買入的時候多減掉一個手續費,相當于股票的買入價格提高了

    def maxProfit(self, prices, fee):""":type prices: List[int]:type fee: int:rtype: int"""n = len(prices)if n == 0:return 0dp = [[0,0] for i in range(n)]for i in range(n):if i == 0:dp[0][0] = 0dp[0][1] = -prices[0]-fee   # 注意這個值else:dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])dp[i][1] = max(dp[i-

LeetCode-123 兩次買賣

k = 2需要考慮狀態,唯一的區別就是base case 設定

# dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+prices[i])
# dp[i][1] = max(dp[i-1][k][1], dp[i-1][k-1][0]-prices[i]),		   
# 需要遍歷k,最多進行兩次,當然我也可以不買賣
def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""k = 2       # 注意k 要能取得到n = len(prices)if n == 0:return 0dp=[[[0,0] for j in range(k+1)] for i in range(n)]for i in range(n):for j in range(k+1):if i == 0 or j ==0:dp[i][j][0] = 0dp[i][j][1] = -prices[0]     # 通用初始化else:dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])return dp[n-1][k][0] 

LeetCode-188 k次買賣

k取任意確定的數字時,解題框架于=與k = 2 時一致。當k 過大時,會造超內存錯誤。根據買賣至少需要兩天,可以限制最大交易次數不應該超過n/2,如果超過了就相當于k = 無窮的情況。整合一下前面的方法即可。

class Solution(object):def maxProfit(self, k, prices):""":type k: int:type prices: List[int]:rtype: int"""n = len(prices)if n == 0:return 0if k > n//2:dp = [[0,0] for i in range(n)]for i in range(n):if i == 0:dp[0][0] = 0dp[0][1] = -prices[0]else:dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])return dp[n-1][0]else:dp=[[[0,0] for j in range(k+1)] for i in range(n)]for i in range(n):for j in range(k+1):if i == 0 or j == 0:dp[i][j][0] = 0dp[i][j][1] = -prices[0]else:dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1]+prices[i])dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i])return dp[n-1][k][0]

2.貪心特解

這兩種特殊情況還是特殊解來的快,框架反而繁雜。

LeetCode-121 一次買賣

關鍵找到每一天之前的最低價格,兩者相減,求增益最大。

def maxProfit(self, prices):n = len(prices)if n == 0:return 0min_val = prices[0]res = 0for i in range(1,n):res = max(res, prices[i]-min_val)min_val = min(min_val, prices[i])return res

LeetCode-122 不限次數

不限次數,每一個谷底買入下一個峰值賣出,多次操作,和值最大。累加收益。


def maxProfit(self, prices):n = len(prices)if n == 0:return 0res = 0 for i in range(1,n):if prices[i]>prices[i-1]:res += prices[i]-prices[i-1]return res

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444963.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444963.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444963.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡游戲的客戶端同步問題 .

有關位置同步的方案實際上已經比較成熟,網上也有比較多的資料可供參考。在《帶寬限制下的視覺實體屬性傳播》一文中,作者也簡單提到了位置同步方案的構造過程,但涉及到細節的地方沒有深入,這里專門針對這一主題做些回顧。 最直接的…

leetcode319 燈泡的開關

初始時有 n 個燈泡關閉。 第 1 輪,你打開所有的燈泡。 第 2 輪,每兩個燈泡你關閉一次。 第 3 輪,每三個燈泡切換一次開關(如果關閉則開啟,如果開啟則關閉)。第 i 輪,每 i 個燈泡切換一次開關。 …

網游服務器端設計思考:心跳設計

網絡游戲服務器的主要作用是模擬整個游戲世界,客戶端用過網絡連接把一些信息數據發給服務器,在操作合法的情況下,更新服務器上該客戶端對應的player實體、所在場景等,并把這些操作及其影響廣播出去。讓別的客戶端能顯示這些操作。…

算法(25)-括號

各種括號1.LeetCode-22 括號生成--各種括號排列組合2.LeetCode-20 有效括號(是否)--堆棧3.LeetCode-32 最長有效括號(長度)--dp4.LeetCode-301刪除無效括號 --多種刪除方式1.LeetCode-22 括號生成–各種括號排列組合 數字 n 代表生成括號的對數,請你設計一個函數&a…

(二十)深入淺出TCPIP之epoll的一些思考

Epoll基本介紹 在linux的網絡編程中,很長的時間都在使用select來做事件觸發。在linux新的內核中,有了一種替換它的機制,就是epoll。相比于 select,epoll最大的好處在于它不會隨著監聽fd數目的增長而降低效率。因為在內核中的select實現中,它是采用輪詢來處理的,輪詢的fd…

leetcode542 01矩陣

給定一個由 0 和 1 組成的矩陣,找出每個元素到最近的 0 的距離。 兩個相鄰元素間的距離為 1 。 示例 1: 輸入: 0 0 0 0 1 0 0 0 0 輸出: 0 0 0 0 1 0 0 0 0 示例 2: 輸入: 0 0 0 0 1 0 1 1 1 輸出: 0 0 0 0 1 0 1 2 1 注意: 給定矩陣的元素個數不超過 10000。…

RPC、RMI與MOM與組播 通信原理 .

遠程過程調用(RPC): 即對遠程站點機上的過程進行調用。當站點機A上的一個進程調用另一個站點機上的過程時,A上的調用進程掛起,B上的被調用過程執行,并將結果返回給調用進程,使調用進程繼續執行【…

網關服務器 .

之前想著要把什么什么給寫一下,每次都太懶了,都是想起了才來寫一下。今天只討論游戲服務器的網關服務器。 1.轉發 轉發客戶端和服務器間的消息,網關將場景、會話、數據、名字、平臺等服務器的數據轉發給客戶端,接收客戶端的數據&a…

算法(26)-最長系列

最長系列1.LeetCode-32 最長有效括號--子串2.LeetCode-300 最長上升子序列--長度3.LeetCode-32 最長回文子串--是什么5.LeetCode-512 最長回文子序列--長度6.LeetCode-1143 最長公共子序列--長度6.LeetCode-128 最長連續序列--長度7.LeetCode-14 最長公共前綴-字符串8.劍指offe…

一個簡單的游戲服務器框架 .

最近一段時間不是很忙,就寫了一個自己的游戲服務器框架雛形,很多地方還不夠完善,但是基本上也算是能夠跑起來了。我先從上層結構說起,一直到實現細節吧,想起什么就寫什么。 第一部分 服務器邏輯 服務器這邊簡單的分為三…

游戲登陸流程 .

當公司有很多游戲的時候,那么公司往往會有一個統一的賬號管理平臺,就就像盛大通行證、網易通行證,戰網平臺,這些平臺統一管理游戲的賬號數據。 打個比方,現在我們玩星辰變,那么玩家登陸游戲的時候…

leetcode97 交錯字符串

給定三個字符串 s1, s2, s3, 驗證 s3 是否是由 s1 和 s2 交錯組成的。 示例 1: 輸入: s1 "aabcc", s2 "dbbca", s3 "aadbbcbcac" 輸出: true 示例 2: 輸入: s1 "aabcc", s2 "dbbca", s3 "aadbbbaccc" 輸…

算法(27)-最大系列

最大系列1.LeetCode-239 滑動窗口的最大值2.LeetCode-53 連續子數組的最大和3.LeetCode-152 乘積最大的子數組。4.劍指 Offer 14- I. 剪繩子為k個整數段,使各個段成績最大1.dp數學推導1.LeetCode-239 滑動窗口的最大值 窗口由左往右最大值數組Left,和由…

mysql數據庫表的導入導出

MySQL寫入數據通常用insert語句,如 復制代碼 代碼如下: insert into person values(張三,20),(李四,21),(王五,70)…; 但有時為了更快速地插入大批量數據或…

leetcode 33 搜索旋轉排序數組 到處是細節的好題

這個題想了想就會做,只是細節真的能卡死人,找了好久的bug。甚至我懷疑我現在的代碼可能還有錯,只是沒例子測出來。 假設按照升序排序的數組在預先未知的某個點上進行了旋轉。 ( 例如,數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1…

多線程中局部靜態變量初始化的陷阱

C當中常常需要一個全局唯一的對象實例,這時候,我們就會想到單件模式。如何實現這一模式?全局變量當然是一個簡單可行的方法,然而,這太丑陋。嗯,其實,丑陋倒也罷了,最嚴重的是它將引誘…

MachineLearning(8)-PCA,LDA基礎+sklearn 簡單實踐

PCA,LDA基礎sklearn 簡單實踐1.PCAsklearn.decomposition.PCA1.PCA理論基礎2.sklearn.decomposition.PCA簡單實踐2.LDAsklearn.discriminant_analysis.LinearDiscriminantAnalysis2.1 LDA理論基礎2.2 sklearn LDA簡單實踐1.PCAsklearn.decomposition.PCA 1.PCA理論基礎 PCA:&…

引用變量和引用數組

前兩天沒事干,重拾C++的一些書籍,翻到引用這,無意寫了些DD: 其實引用和指針有很多相似的地方,又有不同的(太多了,不過說到效率上,比如函數傳參數,我們可以用引用,指針,哪種好呢,引用不必為站再分配空間了,而指針還學要分配4字節的空間給指針變量) 我們知道如何…

leetcode198 打家劫舍

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。 給定一個代表每個房屋存放金額的…

linux下的RPC

一、概述 在傳統的編程概念中,過程是由程序員在本地編譯完成,并只能局限在本地運行的一段代碼,也即其主程序和過程之間的運行關系是本地調用關系。因此這種結構在網絡日益發展的今天已無法適應實際需求。總而言之,傳統過程調用模式…