買賣股票的各種最佳時機問題

買賣股票的最佳時機

分析

根據題意可知,我們只需要找出來一個最小價格的股票和一個最大價格的股票,并且最小價格的股票出現在最大價格的股票之前。

如果嘗試使用暴力解法,時間復雜度為O(N^2),對于題目中給的長度,顯然是會超時的,因此我們需要另尋它法。

我們可以使用一次遍歷,在經過每個值時,計算出包含該值之前的股票的最低價格和最大利潤,該種方法的時間復雜度為O(N),顯然是可解的。

初始化:由于在確定價格最小值時涉及到min求最小值,而且根據題目所給價格的范圍,我們可以使用 0x3f3f3f3f 來初始化minprice;根據題意,由于利潤最小為0,不涉及到為負的情況,因此初始化 profit 為0即可。

填表順序:從左到右。

返回值:profit

代碼

class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();int profit=0,minprice=0x3f3f3f3f;for(int price:prices){profit=max(profit,price-minprice);minprice=min(price,minprice);}return profit;}
};
買賣芯片的最佳時機

分析

根據題意,只需找到一個最低價格和一個最高價格,并且最低價格出現在最高價格之前,顯然與上面的題意是一樣的,解法顯而易見也是一樣的。

代碼

class Solution {
public:int bestTiming(vector<int>& prices) {int n=prices.size();int profit=0,minprice=0x3f3f3f3f;for(int price:prices){profit=max(profit,price-minprice);minprice=min(price,minprice);}return profit;}
};
買賣股票的最佳時機II

分析

如果以以往經驗,對于本題,我們可以定義一個 dp 表,dp[i] 表示以 i 位置為結尾,能獲取的最大利潤,即:

由于題目中涉及到該天“買股票”和“賣股票”的問題,因此,僅僅使用一維 dp 是不能解決問題的,因此可以嘗試使用二維 dp 來解決,dp[i][0] 表示手里沒股票的時候能獲取的最大利潤,dp[i][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-1][0]-prices[i])

初始化:由于只會用到前一行的值,因此只需初始化第一行的值即可,dp[0][0]表示第1天手里沒股票的最大利潤,為0;dp[0][1]表示第一天手里有股票的最大利潤,為 -prices[0]。

填表順序:從上到下。

返回值:dp[n-1][0],因為最后一天手里有股票肯定是比最后一天沒股票要虧。

代碼

class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();vector<vector<int>> dp(n,vector<int>(2));dp[0][1]=-prices[0];for(int i=1;i<n;i++){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];}
};
買賣股票的最佳時機含手續費

分析

?如果以以往經驗,對于本題,我們可以定義一個 dp 表,dp[i] 表示以 i 位置為結尾,能獲取的最大利潤,即:

由于題目涉及到該天“買股票”和“賣股票”這兩種情況,顯然只表示該天為結尾能獲取的最大利潤,是非常模糊的,那么問題也得不到解決。

因此考慮使用二維 dp 來解決問題,dp[i][0]表示第 i 天手里沒股票的時候能獲取的最大利潤;dp[i][1]表示第 i 天手里有股票的時候能獲取的最大利潤(顯然,根據題意,這里所說的有股票指的是“一張股票”)。

狀態轉移方程:dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);

? ? ? ? ? ? ? ? ? ? ? ? ?dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

初始化:由于只會用到前一行的值,因此只需初始化第一行的值即可,dp[0][0]表示第1天手里沒股票的最大利潤,為0;dp[0][1]表示第一天手里有股票的最大利潤,為 -prices[0]。

填表順序:從上到下。

返回值:dp[n-1][0],因為最后一天手里有股票肯定是比最后一天沒股票要虧。

解法一

代碼

class Solution {
public:int maxProfit(vector<int>& prices, int fee) {int n=prices.size();vector<vector<int>> dp(n,vector<int>(2));//dp[i][0] 表示沒股票的最大利潤//dp[i][1] 表示有股票的最大利潤dp[0][1]=-prices[0];for(int i=1;i<n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]-fee);dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);}return dp[n-1][0];}
};
解法二

根據解法一的狀態轉移方程可知,每一次填寫只會用到前一行的兩個值,因此我們可以只定義幾個變量來解決問題。

代碼

class Solution {
public:int maxProfit(vector<int>& prices, int fee) {int n=prices.size();int a=0,b=-prices[0];//a 表示沒股票的最大利潤//b 表示有股票的最大利潤for(int i=1;i<n;i++){int a1=max(a,b+prices[i]-fee);int b1=max(b,a-prices[i]);a=a1,b=b1;}return a;}
};
解法三(貪心)

仔細分析前兩種解法,不難發現,都是在賣出股票的時候進行決策優劣的,我們不妨嘗試在買入股票的時候進行優劣的決策。

定義buy表示買入價格(含手續費),當某天價格+手續費 < buy 的時候,表示我們可以用更低成本賣股票,則更新 buy=prices[i]+fee。

定義profit表示能獲取的最大利潤,當prices[i] > buy的時候,我們會賣出股票,但是這里需要注意的是,如果我們這個時候賣出股票,可能不是最優的,因為可能之后的價格更高,即一張股票可以賺更高的利潤,因此我們可以嘗試以下策略:先賣掉,并把 buy 更新為 prices[i],那么在之后遇到更高價格之后,只需加上差價即可,即:我們是提供了一種“可以反悔”的操作。

代碼

class Solution {
public:int maxProfit(vector<int>& prices, int fee) {int n=prices.size();int buy=prices[0]+fee;int profit=0;for(int i=1;i<n;i++){if(prices[i]+fee < buy)buy=prices[i]+fee;else if(prices[i] > buy){profit+=prices[i]-buy;buy=prices[i];}}return profit;}
};
買賣股票的最佳時期含冷凍期

分析

??如果以以往經驗,對于本題,我們可以定義一個 dp 表,dp[i] 表示以 i 位置為結尾,能獲取的最大利潤,即:

由于題目涉及到該天“買股票”,“賣股票”和“冷凍期”這三種情況,顯然只表示該天為結尾能獲取的最大利潤,是非常模糊的,那么問題也得不到解決。

因此考慮使用二維 dp 來解決問題,dp[i][0]表示第 i 天手里有股票的時候能獲取的最大利潤(顯然,根據題意,這里所說的有股票指的是“一張股票”);dp[i][1]表示手里沒股票,當天處于冷凍期的最大利潤;dp[i][2]表示手里沒股票,當天不處于冷凍期的時候所能獲取的最大利潤。

狀態轉移方程:dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);

? ? ? ? ? ? ? ? ? ? ? ? ?dp[i][1]=dp[i-1][0]+prices[i];

? ? ? ? ? ? ? ? ? ? ? ? ?dp[i][2]=max(dp[i-1][1],dp[i-1][2]);

初始化:根據狀態轉移方程可知,每次填值只會用到上一行的值,因此只需初始化第一行即可,

? ? ? ? ? ? ? dp[0][0]= -prices[0],dp[0][1]=0,dp[0][2]=0。

填表順序:從上到下。

返回值:max(dp[n-1][1],dp[n-1][2]).因為最后一天手里有股票肯定是比最后一天手里沒股票要虧的.

解法一

代碼

class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();vector<vector<int>> dp(n,vector<int>(3));dp[0][0]=-prices[0];//dp[i][0] 手里有股票的最大利潤//dp[i][1] 手里沒股票,處于冷凍期的最大利潤//dp[i][2] 手里沒股票,不處于冷凍期的最大利潤for(int i=1;i<n;i++){dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);dp[i][1]=dp[i-1][0]+prices[i];dp[i][2]=max(dp[i-1][1],dp[i-1][2]);}return max(dp[n-1][1],dp[n-1][2]);}
};
解法二

根據解法一可知,每次填值只會用到上一行的三個值,因此可以嘗試用幾個變量來解決,時間復雜度為O(N)。

代碼

class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();int a=-prices[0],b=0,c=0;//a 手里有股票的最大利潤//b 手里沒股票,處于冷凍期的最大利潤//c 手里沒股票,不處于冷凍期的最大利潤for(int i=1;i<n;i++){int a1=max(a,c-prices[i]);int b1=a+prices[i];int c1=max(b,c);a=a1,b=b1,c=c1;}return max(b,c);}
};
買賣股票的最佳時機III

分析

???如果以以往經驗,對于本題,我們可以定義一個 dp 表,dp[i] 表示以 i 位置為結尾,能獲取的最大利潤,即:

由于該題涉及“買股票”,“賣股票”和“交易次數”的問題,顯然使用一維dp是不能解決問題的。

我們可以使用三維 dp 來解決,dp[i][j][k],i 表示第 i 天,j 表示處于手里有股票還是沒股票,k 表示已交易次數,這樣看來,三維的有點頭疼。

我們不妨可以使用兩個二維dp來解決,f[i][j]表示手里沒股票,已交易 j 次能獲取的最大利潤,g[i][j]表示手里有股票,已交易 j 次能獲取的最大利潤。

狀態轉移方程:f[i][j]=max(f[i-1][[j],g[i-1][j-1]+prices[i])【注意:使用g[i-1][j-1]須滿足 j >=1】

? ? ? ? ? ? ? ? ? ? ? ? ?g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]).

初始化:對于f[i][j]來說,會用到上一行的值,因此只需初始化第一行即可,由于第一行表示第一天,因此最多交易0次,對于高于0次的情況并不可能出現,初始化為 -0x3f3f3f3f.

? ? ? ? ? ? ? 對于g[i][j]來說,會用到上一行的值,也可能用到前一行前一列的值(左上方)【因此不需要初始化】

填表順序:從上到下,從左到右。

返回值:f[i][j]里面的最大值。

代碼

class Solution {
public:int maxProfit(vector<int>& prices) {int n=prices.size();vector<vector<int>> f(n,vector<int>(3,-0x3f3f3f3f));vector<vector<int>> g(n,vector<int>(3,-0x3f3f3f3f));//f[i][j] 表示沒股票的時候,已經交易j次,獲取的最大利潤//g[i][j] 表示有股票的時候,已經交易j次,獲取的最大利潤f[0][0]=0,g[0][0]=-prices[0];for(int i=1;i<n;i++){for(int j=0;j<=2;j++){f[i][j]=f[i-1][j];if(j>=1)f[i][j]=max(f[i][j],g[i-1][j-1]+prices[i]);g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]);}}return *max_element(f[n-1].begin(),f[n-1].end());}
};
買賣股票的最佳時機IV

分析

這道題與上一道題相比,差異之處為上一道題限制交易次數最多為兩次,本題限制交易次數最多為k次,所以解法和代碼同上一道題幾乎? ? 如出一轍。

???如果以以往經驗,對于本題,我們可以定義一個 dp 表,dp[i] 表示以 i 位置為結尾,能獲取的最大利潤,即:

由于該題涉及“買股票”,“賣股票”和“交易次數”的問題,顯然使用一維dp是不能解決問題的。

我們可以使用三維 dp 來解決,dp[i][j][k],i 表示第 i 天,j 表示處于手里有股票還是沒股票,k 表示已交易次數,這樣看來,三維的有點頭疼。

我們不妨可以使用兩個二維dp來解決,f[i][j]表示手里沒股票,已交易 j 次能獲取的最大利潤,g[i][j]表示手里有股票,已交易 j 次能獲取的最大利潤。

狀態轉移方程:f[i][j]=max(f[i-1][[j],g[i-1][j-1]+prices[i])【注意:使用g[i-1][j-1]須滿足 j >=1】

? ? ? ? ? ? ? ? ? ? ? ? ?g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]).

初始化:對于f[i][j]來說,會用到上一行的值,因此只需初始化第一行即可,由于第一行表示第一天,因此最多交易0次,對于高于0次的情況并不可能出現,初始化為 -0x3f3f3f3f.

? ? ? ? ? ? ? 對于g[i][j]來說,會用到上一行的值,也可能用到前一行前一列的值(左上方)【因此不需要初始化】

填表順序:從上到下,從左到右。

返回值:f[i][j]里面的最大值。

代碼

class Solution {
public:int maxProfit(int k, vector<int>& prices) {int n=prices.size();vector<vector<int>> f(n,vector<int>(k+1,-0x3f3f3f3f));vector<vector<int>> g(n,vector<int>(k+1,-0x3f3f3f3f));//f[i][j] 表示沒股票的時候,已經交易j次,獲取的最大利潤//g[i][j] 表示有股票的時候,已經交易j次,獲取的最大利潤f[0][0]=0,g[0][0]=-prices[0];for(int i=1;i<n;i++){for(int j=0;j<=k;j++){f[i][j]=f[i-1][j];if(j>=1)f[i][j]=max(f[i][j],g[i-1][j-1]+prices[i]);g[i][j]=max(g[i-1][j],f[i-1][j]-prices[i]);}}return *max_element(f[n-1].begin(),f[n-1].end());}
};

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

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

相關文章

金士頓U盤被寫保護的解決方法

1.適用的U盤芯片信息 USB設備ID: VID 0951 PID 1666 設備供應商: Kingston 設備名稱: DataTraveler 3.0 設備修訂版: 0110 產品制造商: Kingston 產品型號: DataTraveler 3.0 產品修訂版: PMAP 主控廠商: Phison(群聯) 主控型號: PS2251-07(PS2307) - F/W 08.03.50 [2018-…

從學士-碩士-博士-博士后-副教授-教授-優青-杰青-長江-院士:一文看懂學術巨人的成長歷程

會議之眼 快訊 學術之路&#xff0c;如同攀登一座高聳入云的山峰&#xff0c;需要毅力、智慧和不斷的求知探索。從奠定基礎的學士&#xff0c;到站在學術巔峰的院士。這條成長之路充滿了挑戰和機遇。 如果把學術界比作王者榮耀&#xff0c;那么學者們的成長歷程就像是在進行一…

SpringBoot-SchedulingConfigurer源碼初識:理解定時任務拋異常終止本次調度,但不會影響下一次執行調度

SchedulingConfigurer源碼初識&#xff1a;理解定時任務拋異常終止本次調度&#xff0c;但不會影響下一次執行調度 EnableSchedulingScheduledAnnotationBeanPostProcessor進入finishRegistration方法 ScheduledTaskRegistrar處理觸發器任務&#xff08;TriggerTask&#xff09…

F5G城市光網,助力“一網通城”筑基數字中國

《淮南子》中說&#xff0c;“臨河而羨魚&#xff0c;不如歸家織網”。 這句話在后世比喻為做任何事情都需要提前做好準備&#xff0c;有了合適的工具&#xff0c;牢固的基礎&#xff0c;各種難題也會迎刃而解。 如今&#xff0c;數字中國發展建設如火如荼&#xff0c;各項任務…

訓練營第二十七天 | 491.遞增子序列46.全排列47.全排列 II332.重新安排行程51. N皇后

491.遞增子序列 力扣題目鏈接(opens new window) 給定一個整型數組, 你的任務是找到所有該數組的遞增子序列&#xff0c;遞增子序列的長度至少是2。 示例: 輸入: [4, 6, 7, 7]輸出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 說明: …

S4 BP 常用tcode

FLBPD1 - 從客戶創建業務伙伴 FLBPC1 - 從供應商處創建業務合作伙伴 FLBPD2 - 將業務伙伴鏈接到客戶 FLBPC2 - 業務合作伙伴到供應商的鏈接 CVI_CUSTOMIZING_CHK - 事務 CVI_CUSTOMIZING_CHK CVI_PRECHK - 事務 CVI_PRECHK CVI_COCKPIT - 事務 CVI_COCKPIT MDS_LINKS - …

Python腳本自動填充數據和生成文檔輕松辦公

一&#xff0c;自動填充數據生成word文檔 代碼&#xff1a; from docx import Document# 創建一個新的Word文檔對象 doc Document()# 添加標題 doc.add_heading(自動填充數據和生成文檔, level1)# 添加段落 doc.add_paragraph(這是一個使用Python腳本自動填充數據并生成文檔的…

刷新方盒子最快10萬銷量紀錄 捷途旅行者何以顛覆越野市場?

近年”方盒子“產品迅速崛起&#xff0c;在新一輪的市場角逐中&#xff0c;率先突圍的并非傳統豪強&#xff0c;而是首次進軍越野市場的捷途汽車。作為“燃油車&#xff0c;”捷途旅行者&#xff0c;在面對純電、混動等產品的強勢圍剿下&#xff0c;僅用時9個月便成為細分市場銷…

基于細節增強卷積和內容引導注意的單圖像去霧

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 摘要Abstract文獻閱讀&#xff1a;DEA-Net&#xff1a;基于細節增強卷積和內容引導注意的單圖像去霧1、研究背景2、方法提出3、相關知識3.1、DEConv3.3、多重卷積的…

深度學習 - 構建神經網絡

1. 自動求導機制 概念解釋&#xff1a; 自動求導&#xff1a;PyTorch的autograd模塊允許我們自動計算張量的梯度&#xff0c;這在反向傳播算法中尤為重要。反向傳播是神經網絡訓練的核心&#xff0c;用于計算每個參數的梯度并更新參數。 生活中的例子&#xff1a; 想象你是…

Java時間類(十六) -- 將一天的時間進行等步長分割

廢話不多說,直接上工具類: import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List;/*** @ClassName TimeSplitterUtil* @Description …

C語言指針與數組名的聯系

目錄 一、數組名的理解 a.數組名代表數組首元素的地址 b. 兩個例外 二、使用指針來訪問數組 三、一維數組傳參的本質 一、數組名的理解 a.數組名代表數組首元素的地址 我們在使用指針訪問數組的內容時&#xff0c;有這樣的代碼&#xff1a; int arr[10] {1,2,3,4,5,6,7,…

枚舉(enum)+聯合體(union)

枚舉聯合 一.枚舉類型1.枚舉類型的聲明2.枚舉類型的優點3.枚舉類型的使用 二.聯合體1.聯合體類型的聲明2.聯合體的特點3.相同成員的結構體和聯合體對比4.聯合體大小的計算5.聯合體的練習&#xff08;判斷大小端&#xff09;6.聯合體節省空間例題 一.枚舉類型 1.枚舉類型的聲明…

Sentinel1.8.6更改配置同步到nacos(項目是Gateway)

本次修改的源碼在&#xff1a;https://gitee.com/stonic-open-source/sentinel-parent 一 下載源碼 地址&#xff1a;https://github.com/alibaba/Sentinel/releases/tag/1.8.6 二 導入idea&#xff0c;等待maven下載好各種依賴 三 打開sentile-dashboard這個模塊&#xf…

介紹下CIDR(Classless Inter-Domain Routing)無類別域間路由

最近在搞DELL EMC XtremIO的重新初始化&#xff0c;在Stortage controller和XMS的xinstall配置的時候&#xff0c;需要配置用到CIDR&#xff0c;就是classless inter-domian routing&#xff0c;總結了一下&#xff0c;其實很多對網絡設備的地方都用得到&#xff0c;以前還不知…

華為手機錄屏在哪里?圖文詳解幫你找!

隨著科技的進步&#xff0c;智能手機已成為我們日常生活中不可或缺的工具。其中&#xff0c;華為手機憑借其卓越的性能和用戶體驗&#xff0c;在全球范圍內贏得了廣泛的贊譽。在眾多功能中&#xff0c;錄屏功能尤為實用&#xff0c;無論是制作教程、記錄游戲精彩瞬間&#xff0…

壓敏電阻器是在規定溫度下,當電壓超過某一臨界值時電導隨電壓的升高而急速增大的一種電阻器

壓敏電阻器是在規定溫度下,當電壓超過某一臨界值時電導隨電壓的升高而急速增大的一種電阻器。壓敏電阻器的伏安特性是非線性的,因此,壓敏電阻器亦稱為非線性電阻器,非線性來自于壓敏電阻器兩端的外加電壓,其伏安特性如圖 9-1所示。從圖9-1可以看出,壓敏電阻器有對稱型和非對稱型…

網絡運維簡介

目錄 1.網絡運維的定義 2.誕生背景 3.網絡運維的重要性 4.優點 5.缺點 6.應用場景 6.1.十個應用場景 6.2.數據中心運維 7.應用實例 8.小結 1.網絡運維的定義 網絡運維&#xff08;Network Operations&#xff09;是指管理、監控和維護計算機網絡以確保其高效、安全和…

2024最新華為OD算法題目

在一個機房中,服務器的位置標識在 n*m 的整數矩陣網格中,1表示單元格上有服務器,0 表示沒有。如果兩臺服務器位于同一行或者同一列中緊鄰的位置,則認為它們之間可以組成一個局域網。請你統計機房中最大的局域網包含的服務器個數。 輸入描述 第一行輸入兩個正整數,n和m,…

Python私教張大鵬 Vue3整合AntDesignVue之文本組件

案例&#xff1a;展示標題 核心代碼&#xff1a; <a-typography><a-typography-title>Introduction</a-typography-title> </a-typography>vue3示例&#xff1a; <template><a-typography><a-typography-title>這是一個標題</…