代碼隨想錄刷題筆記 DAY 37 | 動態規劃理論基礎 | 斐波那契數 No.509 | 爬樓梯 No.70 | 使用最小花費爬樓梯 No.746

文章目錄

    • Day 37
      • 00. 動態規劃理論基礎
      • 01. 斐波那契數(No. 509)
        • <1> 題目
        • <2> 筆記
        • <3> 代碼
      • 02. 爬樓梯(No. 70)
        • <1> 題目
        • <2> 筆記
        • <3> 代碼
      • 03. 使用最小花費爬樓梯(No. 746)
        • <1> 題目
        • <2> 筆記
        • <3> 代碼

Day 37

00. 動態規劃理論基礎

最常見的動態規劃題目其實就是 求最值,比如說股票問題、背包問題,都是在求使用怎樣的策略能使得整個系統達到一個最優化的狀態。

這是否和貪心比較類似呢?

其實貪心算法和動態規劃算法的區別還是比較大的,貪心算法每一次的最優解一定 包含 上一次的最優解,是局部的最優推出全局的最優,而動態規劃的最優解不一定包含前一次的最優解,而是有可能是由更前面的部分推出的,所以通常通過 dp[] 數組來將前面的所有最優解來保存下來。

動態規劃其實是一個 窮舉 的過程,得到最優解的前提就是要將所有的可能導致最優解的情況列出來,逐步推出最終的結果,而貪心更像是確定了一個路線,直接來走這個最優的路線,但這種最優通常是一種經驗性的,較難推導的方式,相信做過貪心部分的朋友應該深有體會,這也就導致貪心得到的可能不是最優解,但相對的時間復雜度較低,而動態規劃本質是窮舉就會導致其時間復雜度相對較高。

再來談談動態規劃和暴力解法的區別,比如說斐波那契數列,使用遞歸來求會導致大量的重復計算,所以考慮引入備忘錄,也就是記憶搜索的方法,記憶搜索的方法是自頂向下的,也就是要算 f(5) 要遞歸到 f(1) 才開始計算結果,而且由于遞歸的限制,思考其實可以采用自底向下的方式,從 f(1) 開始向上層遞歸,這其實就是動態規劃的方法。

01. 斐波那契數(No. 509)

題目鏈接

代碼隨想錄題解

<1> 題目

斐波那契數 (通常用 F(n) 表示)形成的序列稱為 斐波那契數列 。該數列由 01 開始,后面的每一項數字都是前面兩項數字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

給定 n ,請計算 F(n)

示例 1:

輸入:n = 2
輸出:1
解釋:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

輸入:n = 3
輸出:2
解釋:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

輸入:n = 4
輸出:3
解釋:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30
<2> 筆記

這道題目相信大家都能比較容易的寫出來,這里以本題為案例看看動態規劃的一些小特點。

動態規劃比較重要的一個點就是 狀態,解題的關鍵在于能否列出正確的 狀態轉移方程,以及這個狀態轉移方程最終能否窮舉出問題的最終答案,其實這就要求這個算法問題具備 最優子結構;因為需要不斷用到前面的狀態來推導后面狀態的最優,這就會引出大量的重復的計算這也就是常說的 重疊子問題,所以使用暴力解法的效率很低。

這道斐波那契數列其實就很好的展示了重疊子問題,但其實并不存在重疊子問題,所以嚴格上并不算動態規劃的題目。

比如計算 f(5),畫出遞歸樹

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

可以看出其實是計算了兩遍 f(3) 的,如果說計算的數字更大,子問題的個數會以指數級的速度增長,時間復雜度為 2n。這就是所謂的重疊子問題。

可以注意到 f(n) 的狀態其實是由 f(n - 1)f(n - 2) 推導出來的,轉移的方式其實就是兩者加和,這樣其實就很容易看出 dp 數組的含義,就是 dp[n] = f(n),狀態轉移公式也順帶推了出來(這就是本題較為簡單的原因),因為這幾步幾乎不用怎么思考。

直接寫出代碼。

<3> 代碼
class Solution {public int fib(int n) {if (n == 0) return 0;if (n <= 2) return 1;int[] dp = new int[n + 1];dp[1] = 1;dp[2] = 1;for (int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}

02. 爬樓梯(No. 70)

題目鏈接

代碼隨想錄題解

<1> 題目

假設你正在爬樓梯。需要 n 階你才能到達樓頂。

每次你可以爬 12 個臺階。你有多少種不同的方法可以爬到樓頂呢?

示例 1:

輸入:n = 2
輸出:2
解釋:有兩種方法可以爬到樓頂。

  1. 1 階 + 1 階
  2. 2 階

示例 2:

輸入:n = 3
輸出:3
解釋:有三種方法可以爬到樓頂。

  1. 1 階 + 1 階 + 1 階
  2. 1 階 + 2 階
  3. 2 階 + 1 階

提示:

  • 1 <= n <= 45
<2> 筆記

本題其實也沒有引入太多的遞歸思想,其實可以看作是下一題 使用最小花費爬樓梯 的一個導入。

本題的 dp 定義其實是較為簡單的,因為要得出 n 階臺階由幾種走法,可以想到就是用 dp[n] 來代表共 n 階由多少種走法。

爬到第一層樓有一種方法,爬到第二層有兩種方法,那爬到第三層其實就有三種方法,一種是通過第一層跨兩步,另一種是第二層跨一步。

很多朋友做這道題的時候會有一個疑問的地方,就是我從第一層走一步再走一步算不算一種方法呢?或者說從第四層走兩次到第五層,這里想不通的朋友是因為沒有將目光放到全局,其實將這些方式寫出來得到的數列是相同的,比如 n = 3 的時候 1 1 1,可以理解成從 2 到 3 的一部分,也可以理解成從 1 跨兩步到 3,計算的話其實就計算其中的一部分即可,否則會出現沖突。

使用遞歸五步法來規范一下:

  1. 確認 dp 的含義:爬到第i層樓梯,有dp[i]種方法
  2. 確認遞推公式:dp[i] = dp[i - 1] + dp[i - 2]
  3. dp 數組如何初始化:題目中說了n是一個正整數,所以 dp[0] 是沒有意義的,而遞歸推出后面的部分有需要兩個元素,所以初始化就初始化 dp[1]dp[2]
  4. 遞歸的遍歷順序:需要用到前面的元素,從前向后遍歷
  5. 嘗試舉例推導
<3> 代碼
class Solution {public int climbStairs(int n) {if (n < 3) return n;int[] dp = new int[n + 1];dp[1] = 1;dp[2] = 2;for (int i = 3; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2]; }return dp[n];}
}

03. 使用最小花費爬樓梯(No. 746)

題目鏈接

代碼隨想錄題解

<1> 題目

給你一個整數數組 cost ,其中 cost[i] 是從樓梯第 i 個臺階向上爬需要支付的費用。一旦你支付此費用,即可選擇向上爬一個或者兩個臺階。

你可以選擇從下標為 0 或下標為 1 的臺階開始爬樓梯。

請你計算并返回達到樓梯頂部的最低花費。

示例 1:

輸入:cost = [10,15,20]
輸出:15
解釋:你將從下標為 1 的臺階開始。

  • 支付 15 ,向上爬兩個臺階,到達樓梯頂部。
    總花費為 15 。

示例 2:

輸入:cost = [1,100,1,1,1,100,1,1,100,1]
輸出:6
解釋:你將從下標為 0 的臺階開始。

  • 支付 1 ,向上爬兩個臺階,到達下標為 2 的臺階。
  • 支付 1 ,向上爬兩個臺階,到達下標為 4 的臺階。
  • 支付 1 ,向上爬兩個臺階,到達下標為 6 的臺階。
  • 支付 1 ,向上爬一個臺階,到達下標為 7 的臺階。
  • 支付 1 ,向上爬兩個臺階,到達下標為 9 的臺階。
  • 支付 1 ,向上爬一個臺階,到達樓梯頂部。
    總花費為 6 。

提示:

  • 2 <= cost.length <= 1000
  • 0 <= cost[i] <= 999
<2> 筆記

有了上一道題的鋪墊其實本題就比較容易了,到達臺階 n 有兩種方式分別是從 n - 1n - 2 到達,所以需要有一個數組來存儲之前的狀態。

  1. 確定dp數組以及下標的含義,使用動態規劃,就要有一個數組來記錄狀態,本題只需要一個一維數組dp[i]就可以了,dp[i]的定義:到達第i臺階所花費的最少體力為dp[i]
  2. 確定遞推公式:dp[i - 1] 跳到 dp[i] 需要花費 dp[i - 1] + cost[i - 1],dp[i - 2] 跳到 dp[i] 需要花費 dp[i - 2] + cost[i - 2],那選擇哪個呢?一定是最小的,所以 dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
  3. dp 數組如何初始化:和上面題目相同,只需要初始化兩個即可,也就是 dp[0]dp[1],分別初始化成 cost[0]ocst[1]
  4. 確定遍歷順序:和上題相同,都是自底向上,從前向后遍歷
  5. 舉例推導,發現沒有問題

通過上面的梳理就能寫出代碼

<3> 代碼
class Solution {public int minCostClimbingStairs(int[] cost) {int n = cost.length;if (n < 2) {return 0;}int[] dp = new int[n + 1];dp[0] = 0;dp[1] = 0;for (int i = 2; i <= n; i++) {dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); }return dp[n];}
}

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

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

相關文章

ECMAScript-262 @2023版本中的關鍵字和保留字

1、什么是標識符&#xff1f; 所謂標識符&#xff0c;就是javascript里的變量、函數、屬性或函數參數的名稱&#xff0c;可由一個或多個字符組成&#xff0c;當然標識符有命名規范 標識符第一個字符必須是 一個字母、下劃線&#xff08;_&#xff09;或美元符號&#xff08;$…

ONLYOFFICE文檔8.0全新發布:私有部署、卓越安全的協同辦公解決方案

ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案 文章目錄 ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案摘要&#x1f4d1;引言 &#x1f31f;正文&#x1f4da;一、ONLYOFFICE文檔概述 &#x1f4ca;二、ONLYOFFI…

【新書推薦】10.2 分支程序設計

稍微復雜一些的程序通常需要做某種條件判斷&#xff0c;然后再決定程序的執行流程。當然也可以無條件跳轉到程序的另一處地址開始執行。本節我們將詳細介紹分支結構的程序設計方法。 針對功能較為復雜的程序&#xff0c;程序開發有一套標準的流程&#xff0c;我們將10.1節中的五…

計算機網絡【網絡安全】

計算機網絡——網絡安全 一、網絡安全問題概述 網絡安全威脅 網絡安全面臨兩大類威脅&#xff0c;被動攻擊和主動攻擊 被動攻擊 指攻擊者從網絡上竊聽他人的通信內容&#xff0c;通常把這類攻擊稱為截獲。 主動攻擊 篡改 攻擊者故意篡改網絡上傳送的報文 惡意程序 拒絕服…

InnoDB索引與優化篇(5)-InnoDB中的查詢優化策略

InnoDB是MySQL數據庫中一種常用的存儲引擎&#xff0c;它具有高性能和可靠性。查詢優化是數據庫開發中非常重要的一環&#xff0c;它能夠幫助我們提高數據庫查詢的效率和性能。在本篇博客中&#xff0c;我們將介紹一些在使用InnoDB存儲引擎時進行查詢優化的常用策略&#xff0c…

貪心 Leetcode 455 分發餅干

分發餅干 Leetcode 455 學習記錄自代碼隨想錄 假設你是一位很棒的家長&#xff0c;想要給你的孩子們一些小餅干。但是&#xff0c;每個孩子最多只能給一塊餅干。 對每個孩子 i&#xff0c;都有一個胃口值 g[i]&#xff0c;這是能讓孩子們滿足胃口的餅干的最小尺寸&#xff1…

神經網絡算法:卷積神經網絡

神經網絡算法&#xff0c;也稱為人工神經網絡算法&#xff0c;是一種模仿人腦神經網絡結構和功能的計算模型。它由多個神經元相互連接而成的網絡組成&#xff0c;每個神經元都有輸入和輸出&#xff0c;并通過學習算法來調整連接權重&#xff0c;從而實現對輸入數據的模式識別和…

JavaScript Web Socket 詳解

Web Socket ? Web Socket&#xff08;套接字&#xff09;的目標是通過一個長時連接實現與服務器全雙工、雙向的通信。在 JavaScript 中創建 Web Socket 時&#xff0c;一個 HTTP 請求會發送到服務器以初始化連接。服務器響應后&#xff0c;連接使用 HTTP 的 Upgrade 頭部從 H…

12、窗口看門狗

目錄 1、窗口看門狗概述 2、常用寄存器和庫函數配置 3、窗口看門狗實驗 1、窗口看門狗概述 之所以稱為窗口就是因為其喂狗時間是一個有上下限的范圍內&#xff08;窗口&#xff09;&#xff0c;你可以通過設定相關寄存器&#xff0c;設定其上限時間&#xff08;下限固定&…

數據結構 棧和隊列 力扣例題AC——代碼以及思路記錄

20. 有效的括號 給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。左括號必須以正確的順序閉合。每個右括號都有一個對應…

mysql使用連接池

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、mysql連接池&#xff1f;二、使用步驟1.引入庫 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 例如&#xff1a; 提示&#xff1a…

深入理解Flutter中的StreamSubscription和StreamController

在Flutter中&#xff0c;StreamSubscription和StreamController是處理異步數據流的重要工具。它們提供了一種方便的方式來處理來自異步事件源的數據。本文將深入探討它們的區別以及在實際應用中的使用場景。 StreamSubscription StreamSubscription代表了對數據流的訂閱&…

代碼隨想錄算法訓練營番外 刷題日記0301 || 29、兩數相除,31、下一個排列

29、兩數相除 思路&#xff1a;不斷相減就是求解的最直接方法&#xff0c;我這樣計算時間復雜度有點高 // 時間復雜度O(count*divisor) // 空間復雜度O(1)class Solution {int res 0;public int divide(int dividend, int divisor) {// dividend 是被除數if(dividend 0) …

技術棧選型的時候,ruby、go、java、vue、react應該怎么選擇?

選擇適合項目需求、團隊技術背景和偏好、開發速度、性能要求以及可擴展性的技術棧和框架是一個綜合考慮的過程&#xff0c;沒有一種通用的最佳選擇&#xff0c;取決于具體情況。 選擇Vue.js或React應該綜合考慮項目的需求、團隊的技術背景和偏好、生態系統的支持和發展趨勢等因…

隨記-點選驗證碼

文字驗證碼&#xff08;點擊文字&#xff09; 模板匹配&#xff08;從一張圖片中尋找 icon&#xff09;&#xff0c;放棄&#xff0c;目前準確率不高&#xff0c;且處理過程復雜 灰度處理將 complete_image_path 截取并另存為 target_image_path&#xff0c; verify_image_path…

WPF真入門教程30--順風物流單據管理系統

1、教程回顧 到現在為止&#xff0c;真入門系列教程已完成了29刺由淺入深地講解&#xff0c;當然不可能講到了WPF的所有技能點&#xff0c;但讀者看到了wpf的內部各種功能及之間的聯系&#xff0c;在此基礎上&#xff0c;提供一個完整有效的綜合項目&#xff0c;本項目采用的是…

c++知識點之 --this

在成員函數中存在。struct和class每個成員函數都隱含一個名為this的指針形參&#xff0c;并且它是該成員函數的第一個參數&#xff0c;當某個對象調用成員函數時&#xff0c;就會把該對象的地址傳給被調用成員函數的隱式形參this。 this是一個指針 &#xff0c;存放的是當前對象…

加密與安全_深入了解Hmac算法(消息認證碼)

文章目錄 PreHMAC概述常見的Hmac算法Code隨機的key的生成 KeyGeneratorHmacMD5用Hmac算法取代原有的自定義的加鹽算法 HmacMD5 VS MD5HmacSHA256 Pre 加密與安全_深入了解哈希算法中我們提到&#xff0c; 存儲用戶的哈希口令時&#xff0c;要加鹽存儲&#xff0c;目的就在于抵…

操作系統系列學習——CPU管理的直觀想法

文章目錄 前言CPU管理的直觀想法 前言 一個本碩雙非的小菜雞&#xff0c;備戰24年秋招&#xff0c;計劃學習操作系統并完成6.0S81&#xff0c;加油&#xff01; 本文總結自B站【哈工大】操作系統 李治軍&#xff08;全32講&#xff09; 老師課程講的非常好&#xff0c;感謝 【…

OpenLayers線性漸變和中心漸變(徑向漸變)

目錄 1.前言2.添加一個面要素3.線性漸變3.1 第一個注意點3.2 第二個注意點 4.中心漸變&#xff08;徑向漸變&#xff09;5.總結 1.前言 OpenLayers官網有整個圖層的漸變示例&#xff0c;但是沒有單個要素的漸變示例&#xff0c;我們這里來補充一下。OpenLayers中的漸變是通過fi…