LeetCode 121. 買賣股票的最佳時機 LeetCode 122. 買賣股票的最佳時機II LeetCode 123.買賣股票的最佳時機III

LeetCode 121. 買賣股票的最佳時機

嘗試一:暴力解決方法

常用兩個指針去遍歷prices數組,dp[i]用于記錄在第i天所獲得的最大利潤。時間復雜度是O(N^2),超出時間限制。

Code

class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""## 買入賣出的次數 <= 1## 1. dp數組定義。## dp[i] 表示第i天前所獲得的最大利潤## 2. dp初始化dp = [0] * (len(prices))## 3. 遞推公式## 利潤: diff = price[j] - price[i]## 第j天的利潤大于等第i天利潤,那么第j天利潤 = 第i天利潤 + 第j天價格 - 第i天價格## dp[j] = max(dp[j], dp[i] + prices[j] - prices[i])## 4. 遍歷順序for i in range(len(prices)):for j in range(i+1, len(prices)):if prices[j] > prices[i]:dp[j] = max(dp[j], dp[i] + prices[j] - prices[i])## 5. 打印dp數組return max(dp)

動規的思路:

1. dp數組定義:第i天時,我目前的狀態有兩種,一種是持有股票,另外一種是已賣出股票,因此dp數組是一個二維數組,第一維用來表示天數,第二維用來表示在這一天我目前手頭的股票狀態。因此,dp[i][0]表示為?天數<= i?時我已購入一只股票, dp[i][1]表示為 天數 <= i?時?我已賣出一只股票后所獲得的最大利潤。

2. dp數組初始化:?由于遞推公式是前面推后面,因此第一個元素需要初始化。

  • dp[0][0] = -prices[0]:?第0天持有購買,是消費行為。為什么是-prices[0],其實是因為現有手頭現金為0,因此是0-prices[0],結果就是-prices[0]
  • dp[0][1] = 0:?第0天賣出股票沒有利潤可言。
  • 另外,由于dp[i][0]是針對負數求最大化,因此dp數組要用負無窮去初始化,再對特殊值進行初始化。

3. 遞推公式:

  • dp[i][0]的情況有兩種:第i天前已購買(dp[i-1][0]) /?第?i?天時才購買( 現有金額 -prices[i],?負號表示購買,是虧損了這么多錢,而本題只有買賣一次,因此現有金額是0),為獲得最大利潤,我要盡可能以低的價格購入股票,因此dp[i][0] =?max(dp[i-1][0], -prices[i])
  • 相應地,dp[i][1]的情況也有兩種:第i天前已賣出(dp[i-1][1]) /?第?i?天時才賣出(利潤 = prices[i] - dp[i-1][0] (第i天前買入的股票才可以在第i天時賣出) ),那最大利潤遞推公式就是dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i]) 。

Code

class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""# 1. dp數組定義。由于第i天的現有股票有兩種狀態,一個是已買入,一個是已賣出,因此需要用一個長度為2的數組來表示這種關系
# dp[i][0], 表示第i天已買入股票的狀態,這種狀態描述了我在第i天前(包括第i天)購入了一只股票,值表示我購入這支股票所花的錢
# dp[i][1], 表示第i天已賣出股票的狀態,這種狀態描述了我在第i天前(包括第i天)賣出了一只股票,值表示我賣出這支股票所花的錢dp = [[-float('inf')] * 2 for _ in range(len(prices))]# 2. dp初始化dp[0][0] = -prices[0]dp[0][1] = 0# 3. 遞推公式# dp[i][0] = max(dp[i-1][0], -prices[i])# dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i])  # dp[i-1][0]+prices[i]表示第i天賣出時得到的利潤# 4. 遍歷順序for i in range(len(prices)):dp[i][0] = max(dp[i-1][0], -prices[i])dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i])# 5. 打印dp數組if dp[-1][1] < 0:    ## 表示虧損了,那還不如不買return 0return dp[-1][1]

LeetCode 122.買賣股票的最佳時機II

思路一:貪心算法

只要有正利潤就貪下來

Code

class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""## 思路一:可以用貪心思路解決dp = [0] * len(prices)for i in range(1, len(prices)):margin = prices[i] - prices[i-1]if margin > 0:dp[i] = marginall_margin = sum(dp)return all_margin

思路二:動態規劃

思路:

與第一題相比關鍵在于可以買賣多次,那第一題只能買賣一次,因此起始資金始終為0。而可以買賣多次的話,你在后續賺到錢后到起始資金就不是0了,因此這是與上道題的最大區別。

遞推公式:

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

  • dp[i][0] = dp[i-1][0],第i天不買入股票。
  • dp[i][0] = dp[i-1][1] - prices[i], 第i天買入股票,那現在就需要起始金額-購買股票金額了,起始金額為之前賺到的利潤dp[i-1][1]。

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

  • dp[i][1] ?= dp[i-1][1],第i天不賣出股票。
  • dp[i][1] = dp[i-1][0] + prices[i],第i天賣出股票,那就需要在之前買入股票的剩余錢的基礎上 + 賣出這只股票所得到的錢。

總結:dp[i][0]表示我在第i天前(包括第i天)買入股票后手頭上的錢,dp[i][1]表示我在第i天前(包括第i天)賣出股票后所獲得的總利潤。

Code

class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""## 思路二:動態規劃# 1. dp數組定義dp = [ [float("-inf")]*2 for _ in range(len(prices)) ]# 2. dp初始化dp[0][0] = -prices[0]       ##  起始資金為0dp[0][1] = 0# 3. 遞推公式# dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i])# dp[i][1] = max(dp[i][0], dp[i-1][1] + prices[i])# 4. 遍歷順序for i in range(1, len(prices)):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])# 5. 打印dp# print(dp)return dp[-1][1]

LeetCode 123.買賣股票的最佳時機III

買賣股票的最佳時機Ⅰ是只能進行一筆交易

買賣股票的最佳時機Ⅱ是可以進行多筆交易

這道題是兩筆交易,如果設置一個count來計算交易的次數,從左向右交易一次就count+1

但這種做法會陷入你前面兩筆交易雖賺了,但并不是全局的最優。

思路:

  • 為什么這道題要涉及到用多個狀態來進行描述,主要影響因素在于交易次數的限制,多筆交易也可以采用多種狀態來進行描述,但是由于不知道具體交易的次數,因此可以只有兩個狀態來進行買入和賣出的操作,并且這個買入和賣出可以繼承之前已交易后的狀態。
  • 本題是兩次交易,一次交易有兩個狀態,分別是買入和賣出,因此兩次交易要通過4個狀態進行描述,后面的狀態依賴于前面的狀態。

1. dp數組定義

  • dp[i][0]: 在第i天前(包括第i天)不進行股票的買入和賣出操作 ?(這個狀態可以不要)
  • dp[i][1]: ..., 第一次持有股票
  • dp[i][2]: ..., 第一次賣出股票
  • dp[i][3]: ..., 第二次持有股票
  • dp[i][4]: ..., 第二次賣出股票
  • 可以看到1,2?是用來衡量第一筆交易的狀態,3,4是用來衡量第二筆交易的狀態

2. dp初始化

  • dp[0][0] = 0,? ? ? ? ? ? ?表示在第一天不進行任何操作
  • dp[0][1] = -prices[0],表示在第一天第一次買入股票
  • dp[0][2] = 0,? ? ? ? ? ? ?表示在第一天第一次賣出股票
  • dp[0][3] = -prices[0],?表示在第一天第二次買入股票
  • dp[0][4] = 0,? ? ? ? ? ? ? 表示在第一天第二次賣出股票

3. 遞推公式

  • dp[i][0] = dp[i-1][0]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 表示延續之前的不操作狀態
  • dp[i][1] = max(dp[i-1][1], -prices[i])

dp[i][1] = dp[i-1][1],? 第一次操作,表示不買入股票,此時延續第i天之前買入股票后的狀態;

dp[i][1] = -prices[i],第一次操作,表示買入股票,此時起始金額為0,因此是 0 -?prices[i]

  • dp[i][2] = max(dp[i-1][2], prices[i]+dp[i-1][1])

dp[i][2] = dp[i-1][2],?? 第一次操作,表示不賣出股票,此時延續第i天之前不賣出股票后的狀態;

dp[i][2] = prices[i]+dp[i][1],第一次操作,表示賣出股票,此時賣出所得prices[i] +?之前持有股票的狀態dp[i-1][1]?就得到了凈利潤

  • dp[i][3] = max(dp[i-1][3], -prices[i]+dp[i-1][2])

dp[i][3] = dp[i-1][3],?? 第二次操作,表示買入股票,此時延續第i天之前不買入股票后的狀態;

dp[i][3] = -prices[i]+dp[i-1][2],第二次操作,表示買入股票,此時起始金額為dp[i-1][2],因此是 dp[i-1][2] -?prices[i]

  • dp[i][4] = max(dp[i-1][4], prices[i]+dp[i-1][3])

dp[i][4] = dp[i-1][4],?? 第二次操作,表示不賣出股票,此時延續第i天之前不賣出股票后的狀態;

dp[i][4] = prices[i]+dp[i-1][1],第二次操作,表示賣出股票,此時賣出所得prices[i] +?之前持有股票的狀態dp[i-1][3]?就得到了兩次交易后得到的凈利潤。

Code

class Solution(object):def maxProfit(self, prices):""":type prices: List[int]:rtype: int"""# 1. dp數組定義:# 由于一共是兩筆交易,因此買入賣出的次數是4次,因此需要通過4個狀態來衡量這兩筆交易# dp[i][0]: 在第i天前(包括第i天)不進行股票的買入和賣出操作  (這個狀態可以不要)# dp[i][1]: ..., 第一次持有股票# dp[i][2]: ..., 第一次賣出股票# dp[i][3]: ..., 第二次持有股票# dp[i][4]: ..., 第二次賣出股票# 可以看到1,2 用來衡量第一筆交易的狀態,3,4用來衡量第二筆交易的狀態dp = [[float('-inf')]*5 for _ in range(len(prices))]# 2. dp數組初始化dp[0][0] = 0dp[0][1] = -prices[0]dp[0][2] = 0dp[0][3] = -prices[0]dp[0][4] = 0# 3. 遞推公式# dp[i][0] = dp[i-1][0]# dp[i][1] = max(dp[i-1][1], -prices[i])# dp[i][2] = max(dp[i-1][2], prices[i]+dp[i][1])# dp[i][3] = max(dp[i-1][3], -prices[i]+dp[i-1][2])# dp[i][4] = max(dp[i-1][4], prices[i]+dp[i-1][3])# 4.遍歷順序for i in range(1, len(prices)):dp[i][0] = dp[i-1][0]        dp[i][1] = max(dp[i-1][1], -prices[i])dp[i][2] = max(dp[i-1][2], prices[i]+dp[i-1][1])dp[i][3] = max(dp[i-1][3], -prices[i]+dp[i-1][2])dp[i][4] = max(dp[i-1][4], prices[i]+dp[i-1][3])# 5. 打印dp數組# print(dp)return dp[-1][4]

另外,可以看到dp[i][0]的這個定義是不起作用的,因此實際可以只定義4個狀態,沒必要多定義一個不進行任何操作的狀態。

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

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

相關文章

【LeNet網絡架構】——深度學習.卷積神經網絡

目錄 1 MLP 2 LeNet簡介 3 Minst數據集 3.1 MINST數據集簡介 3.2 MNIST數據集的預處理 4 LeNet手寫數字識別 LeNet由Yann Lecun 提出&#xff0c;是一種經典的卷積神經網絡&#xff0c;是現代卷積神經網絡的起源之一。Yann將該網絡用于郵局的郵政的郵政編碼識別&#xff…

Python筆記完整版

常用pip源 &#xff08;1&#xff09;阿里云 http://mirrors.aliyun.com/pypi/simple/&#xff08;2&#xff09;豆瓣 http://pypi.douban.com/simple/&#xff08;3&#xff09;清華大學 https://pypi.tuna.tsinghua.edu.cn/simple/&#xff08;4&#xff09;中國科學技術大學…

2025 鴻蒙創新賽又來了,萬少教你如何強勢切入 HarmonyOS AI特性

2025 鴻蒙創新賽又來了&#xff0c;萬少教你如何強勢切入 前言 ? 2025 華為HarmonyOS 創新賽又來了&#xff0c;創新賽是鴻蒙生態最大規模開發者官方賽事&#xff0c;最高獲百萬激勵。 參賽資格 面向所有開發者開放以隊伍的形式來參加&#xff0c;可以一個人報名一個隊伍&a…

【智能模型系列】Unity通過訪問Ollama調用DeepSeek模型進行本地部署

【智能模型系列】Unity通過訪問Ollama調用DeepSeek模型進行本地部署 目錄 一、前言 二、環境準備 三、核心代碼解析 1、參數配置 2. CallDeepSeek.cs - API交互控制器 3、 MainPanel.cs - 用戶界面控制器 四、源碼 一、前言 在本教程中,我將分享如何在Unity中集成本地…

什么是5G-A三防平板?有什么特點?哪些領域能用到?

在工業自動化與數字化轉型浪潮中&#xff0c;三防平板電腦已成為“危、急、特”場景的核心工具。這類設備不僅具備堅固耐用的物理防護特性&#xff0c;更融合了先進的通信技術與智能處理能力。而隨著5G技術向5G-A階段演進&#xff0c;新一代三防平板正為行業應用注入全新動能。…

Flink實時流量統計:基于窗口函數與Redis Sink的每小時PV監控系統(學習記錄)

題目&#xff1a;利用flink統計網站瀏覽量&#xff0c;并寫入redis。利用窗口函數以及算子實現每小時PV&#xff08;網站的頁面瀏覽量&#xff09;統計&#xff0c;對統計后結果數據格式進行設計&#xff0c;存儲至Redis中&#xff08;利用sink將處理后結果數據輸出到redis數據…

使用Imgui和SDL2做的一個彈球小游戲-Bounze

使用Imgui和SDL2做的一個彈球小游戲-Bounze 油管上面TheCherno博主分享的一個視頻FIRST GAME in C! Did He Do a Good Job? // Code Review (C/SDL2)里面分享了一個Github項目&#xff1a; https://github.com/staticaron/Bounze 使用了Imgui和SDL2&#xff0c;并且可以設置音…

SQL 中 CASE WHEN 及 SELECT CASE WHEN 的用法

SQL 中 CASE WHEN 及 SELECT CASE WHEN 的用法 CASE WHEN 是 SQL 中非常實用的條件表達式&#xff0c;它允許你在查詢中實現條件邏輯。以下是詳細的用法說明&#xff1a; 1. 基本語法結構 CASE WHEN condition1 THEN result1WHEN condition2 THEN result2...ELSE default_resul…

CentOS 7 Linux 基礎知識點匯總

&#x1f427; CentOS 7 Linux 基礎知識點匯總為方便初學者快速掌握 CentOS 7 系統的核心操作&#xff0c;本文檔整理了常用系統命令、快捷鍵、目錄結構及文件后綴名等基礎內容&#xff0c;適合入門參考。 一、常見系統命令 &#x1f50d; 命令行提示符說明 終端中的提示符包含…

突發限制下的破局之路:國產之光 Lynx 重構 AI 開發安全壁壘

繼 Pro 套餐 “明升暗降” 爭議后&#xff0c;Cursor 本周再掀波瀾 —— 包括 Claude 系列、GPT-4 在內的主流模型一夜之間對中國用戶全面封禁。開發者社群瞬間沸騰&#xff0c;“付費卻用不了”“項目數據導不出” 的焦慮刷屏&#xff0c;境外工具的政策波動再次給行業敲響警鐘…

滲透測試實戰 | docker復雜環境下的內網打點

本文作者&#xff1a;Track-syst1m一.前言本文涉及的相關漏洞均已修復、本文中技術和方法僅用于教育目的&#xff1b;文中討論的所有案例和技術均旨在幫助讀者更好地理解相關安全問題&#xff0c;并采取適當的防護措施來保護自身系統免受攻擊。二.大概流程1. 外網打點漏洞利用?…

阿里云服務器 CentOS 7 安裝 MySQL 8.4 超詳細指南

阿里云服務器 CentOS 7 安裝 MySQL 8.4 超詳細指南 一、準備工作 系統要求&#xff1a; CentOS 7.9 64位2 核&#xff08;vCPU&#xff09;2 GiBroot 用戶權限 服務器連接工具&#xff1a; FinalShell 下載安裝包&#xff1a; 訪問 MySQL 官網選擇版本&#xff1a;MySQL 8.4.0…

解決 Electron 中 window.open 打開新窗口的各種“坑”

嘿&#xff0c;各位開發者們&#xff01;今天我們要聊聊在使用 Electron 時遇到的一個經典問題&#xff1a;如何正確地使用 window.open 來打開新窗口&#xff1f; 這聽起來似乎很簡單&#xff0c;但實際上卻充滿了各種“驚喜”&#xff08;或者說“驚嚇”&#xff09;。別擔心…

朝歌智慧盤古信息:以IMS MOM V6重構國產化智能終端新生態

隨著5G、云計算、AI、大數據等技術深度滲透&#xff0c;智能終端行業正迎來場景化創新的爆發期。面對市場需求升級與技術迭代壓力&#xff0c;國產化智能終端領域領軍企業——廣東朝歌智慧互聯科技有限公司&#xff08;以下簡稱“朝歌智慧”&#xff09;&#xff0c;基于集團“…

docker 離線安裝postgres+postgis實踐

文章目錄前言一、離線安裝docker二、導出導入PG鏡像1.導出2.導入三、啟動容器四、驗證與測試前言 在企業內網環境中部署地理信息系統&#xff08;GIS&#xff09;時&#xff0c;常常面臨網絡隔離導致無法在線拉取 Docker 鏡像的問題。 本文將詳細介紹如何通過離線方式完成 Pos…

視頻、音頻錄制

1&#xff0c;項目介紹。 實現全屏錄屏、選擇區域錄屏、攝像頭錄像、麥克風錄音、主板音頻錄音、截屏畫板的自由組合。并通過FFmpeg完成音頻與視頻的合并。 功能界面 畫板畫筆 參考的項目 https://github.com/yangjinming1062/RecordWin 本項目是在此項目的基礎上修復了部…

Linux文件系統理解1

目錄一、初步理解系統層面的文件1. 文件操作的本質2. 進程管理文件核心思想二、系統調用層1. 打開關閉文件函數2. 讀寫文件函數三、操作系統文件管理1. 文件管理機制2. 硬件管理機制四、理解重定向1. 文件描述符分配規則2. 重定向系統調用3. 重定向命令行調用五、理解緩沖區1. …

科技向善,銀發向暖:智慧養老與經濟共筑適老未來

人口老齡化是當今中國社會面臨的重大課題&#xff0c;也是推動社會變革與經濟轉型的重要引擎。隨著數字技術的飛速發展&#xff0c;“智慧養老”正以科技向善的溫度&#xff0c;為老年群體構建更舒適、更安全、更有尊嚴的晚年生活&#xff0c;同時為銀發經濟注入蓬勃活力&#…

numpy庫 降維,矩陣創建與元素的選取,修改

目錄 1.降維函數ravel()和flatten ravel(): flatten(): 2.矩陣存儲與內存結構 3.修改矩陣形狀的方法 4.特殊矩陣創建 全零矩陣: 如np.zeros(5) 創建含5個零的一維數組&#xff0c;輸出中零后的點&#xff08;如 0.&#xff09;表示浮點數類型。 全一矩陣&#xff1a;如n…

SpringCloud seata全局事務

項目https://github.com/apache/incubator-seata docker拉取啟動server $ docker run --name seata-server -p 8091:8091 apache/seata-server:2.1.0 seata注冊到nacos <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-…