代碼隨想錄算法訓練營第60期第四十二天打卡

? ? ? ? 大家好,今天還是繼續我們的動態規劃里面的背包問題,前面我們主要接觸的是0-1背包和完全背包,其實這兩個背包問題主要就是看看每一件物品我們是否有多件,如果每一件物品我們只能取一次的話那這樣我們就是0-1背包,如果每一件物品我們可以取多件的話那這樣就是完全背包,那我們就接著以前的來繼續我們今天的題目。

第一題對應力扣上編號為322的題目零錢兌換

? ? ? ? ? 這道題大家聽到題目名字應該就會有種熟悉的感覺,我們是不是前面做過,是的我們前面的確做過一道關于零錢兌換的題目,而且我們在貪心算法章節還刷過一道叫做檸檬水找零的題目,那我們看看這道題目跟我們以前做過的有什么不一樣的:

? ? ? ? 其實這道題目的背景與我們前面的那道零錢兌換的題目是一樣的,不過那道題目讓我們求的是可以湊出給定數額的組合方案數,而這一道題目讓我們求的是湊出給定數額的所需的最少硬幣個數,其實很明顯題目還是很經典的完全背包問題,因為我們每種硬幣的數量是無限的,但本題和純完全背包不一樣,純完全背包是湊成背包最大價值是多少,而本題是要求湊成總金額的物品最少個數!那我們還是嘗試使用完全背包問題來解決,還是動用動規五部曲。

? ? ? ?首先動規五部曲的第一步就是確定dp數組的含義,其實這里的話我們使用一維dp數組就可以了,dp[j]:湊足總額為j所需錢幣的最少個數為dp[j]。

? ? ? ?第二步就是確定遞推公式,我們需要仔細考慮一下,因為題目要求我們去求湊出給定金額的最少的錢幣數,所以我們可以大致猜測肯定要出現取min值,我們很容易知道湊足總額為j - coins[i]的最少個數為dp[j - coins[i]],那么只需要加上一個錢幣coins[i]即dp[j - coins[i]] + 1就是dp[j](考慮coins[i],那如果不考慮coins[i]呢?那就是dp[j], 那這樣兩個取最小值不就是我們的遞推公式了。

? ? ? ?第三步就是初始化dp數組,我們首先湊足總金額為0所需錢幣的個數一定是0,那么dp[0] = 0;

這個是很明顯的,考慮到遞推公式的特性,dp[j]必須初始化為一個最大的數,否則就會在min(dp[j - coins[i]] + 1, dp[j])比較的過程中被初始值覆蓋。因為我們每一次都要取最小值,這樣可以保證每次都可以正確更新所需的最少錢幣數。

? ? ? ? 第四步就是確定遍歷順序,本題求錢幣最小個數,那么錢幣有順序和沒有順序都可以,都不影響錢幣的最小個數。那其實我們先遍歷錢幣再遍歷金額是可以的,反過來也是可以的。

? ? ? ? 還有一步比較重要的就是舉例推導dp數組,以代碼隨想錄的例子為例:

? ? ? ? ? ?那我們可以嘗試給出代碼:

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX);//初始化dp數組dp[0] = 0;//先遍歷錢幣再遍歷總額for (int i = 0; i < coins.size(); ++i){for (int j = coins[i]; j <= amount; ++j){//如果被更新了就說明存在最少的硬幣數而且可以被湊出if (dp[j - coins[i]] != INT_MAX){dp[j] = min(dp[j - coins[i]] + 1, dp[j]);}}}if (dp[amount] == INT_MAX) return -1;return dp[amount];}
};

?第二題對應力扣編號為279的題目完全平方數

? ? ? ? ?這是我們今天的第二題,這道題我們以前沒有見過比較類似的背景,我們就直接看看這道題目的要求:

? ? ? ? 讀完題目之后我就知道了,其實就是湊出這個數我們至少需要幾個完全平方數,這個題目似乎與上一道題目比較類似,其實都是填滿背包至少需要多少件物品類型題目,很明顯這個題目還是完全背包,那我們還是得用動規五部曲來解決。

? ? ? ? 第一步還是確定dp數組的含義,dp[j]:和為j的完全平方數的最少數量為dp[j]。

? ? ? ? 第二步就是遞推公式,這道題目的遞推公式與上一道題目的遞推公式是異曲同工,還是我們考慮我是是否使用當前的完全平方數,當然我們不需要去寫一個函數判斷一個數是不是完全平方數,這里的每一個數就相當于我們上一道題的錢幣金額,所以我們的遞推公式大家或許就知道了應該是dp[j] = min(dp[j - i * i] + 1, dp[j])。

? ? ? ? 第三步一樣的思路還是dp數組的初始化,dp[0] = 0其實這里可能有同學存在疑問,明明0*0 = 0那為啥dp[0] = 1不對呢,看題目描述,找到若干個完全平方數(比如 1, 4, 9, 16, ...),題目描述中可沒說要從0開始,dp[0]=0完全是為了遞推公式。所以其實這個dp[0] = 0沒有什么意義,從遞歸公式dp[j] = min(dp[j - i * i] + 1, dp[j]);中可以看出每次dp[j]都要選最小的,所以非0下標的dp[j]一定要初始為最大值,這樣dp[j]在遞推的時候才不會被初始值覆蓋。這里其實與我們上面的題目也是類似的。

? ? ? ?第四步就是確定遍歷順序,我們還是使用完全背包的思路,先遍歷物品再遍歷背包就可以了。

? ? ? ? 第五步就是打印驗證dp數組這里就不說了,這個大家可以自行去測試。接下來走完動規五部曲以后我們就可以寫出這道題目的解題代碼:

class Solution {
public:int numSquares(int n) {vector<int> dp(n + 1, INT_MAX);dp[0] = 0;//遍歷物品for (int i = 1; i <= n; ++i){//遍歷背包其實也就是我當前使用完全平方數和湊出來的和for (int j = i * i; j <= n; ++j){//這是我們的遞推公式,如果我想用一個i * i湊出的完全平方數就得先看前面那個數的需要//完全平方數的個數然后加1就可以了dp[j] = min(dp[j - i * i] + 1, dp[j]);}}return dp[n];}
};

第三題對應力扣編號為139的題目單詞拆分

? ? ? ?這是我們今天的最后一道題目,我們動態規劃章節似乎也沒有遇到過背景相似的題目,所以我們就先看看題目的要求:

? ? ? ?題目是給我們一個字符串列表里面存放了一些單詞,給定我們一個字符串,看看這個字符串是否可以由我們字符串列表里面的單詞拼接出來,而且字符串列表里面的單詞都是可以重復使用的,很明顯這還是一道完全背包的問題,那我們還是使用動規五部曲來解決這道題目。

? ? ? 第一步確定dp數組以及下標的含義:dp[i] : 字符串長度為i的話,dp[i]為true,表示可以拆分為一個或多個在字典中出現的單詞。這題目有點特殊,所以我們定義的dp數組也是有點奇怪,第一次出現過bool類型的dp數組。

? ? ? ?第二步就是我們的確定遞推公式,這或許很奇怪,既然我們的dp數組都定義成了bool類型的那我們還有什么遞推公式,其實是這樣的:如果確定dp[j] 是true,且 [j, i] 這個區間的子串出現在字典里,那么dp[i]一定是true。(j < i )。這個聽起來很抽象其實不難理解,我們dp[j]已經湊出了,只要我們[j,i]的區間里面存在我們長度為j與長度為i相差的字符串,那不就說明長度為i的字符串也可以被湊出了。這個思路很有趣,大家要好好積累一下。

? ? ? ?第三步是dp數組如何初始化,從遞推公式中可以看出,dp[i] 的狀態依靠 dp[j]是否為true,那么dp[0]就是遞推的根基,dp[0]一定要為true,否則遞推下去后面都都是false了。大家可以想想其實題目也說了我們的字符串是非空的,其實dp[0]完全是為了遞推公式服務。

? ? ? ?第四步就是遍歷順序,這其實還是一道完全背包的題目,那我們其實還是可以按照完全背包的遍歷順序,其實單詞就是物品,題目所給字符串就是背包,題目還是有需要注意的地方,這道題目是在意順序,其實也就是排列問題而不是組合問題,如何理解?拿 s = "applepenapple", wordDict = ["apple", "pen"] 舉例。"apple", "pen" 是物品,那么我們要求 物品的組合一定是 "apple" + "pen" + "apple" 才能組成 "applepenapple"。"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么我們就是強調物品之間順序。所以我們就知道了這道題目我們就只能先遍歷背包再遍歷物品,如果我們先遍歷物品再遍歷背包就會出現亂序的情況,這點大家必須注意。

? ? ? ?那這樣其實題目的代碼與以前似乎還是有些不一樣:

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());vector<bool> dp(s.size() + 1, false);dp[0] = true;for (int i = 1; i <= s.size(); i++) {   // 遍歷背包for (int j = 0; j < i; j++) {       // 遍歷物品string word = s.substr(j, i - j); //substr(起始位置,截取的個數)if (wordSet.find(word) != wordSet.end() && dp[j]) {dp[i] = true;}}}return dp[s.size()];}
};

?今日總結

? ? ? ?我們今天的題目其實有難度,大家得多多思考,理解動態規劃并不容易,尤其是單詞拆分這道題目的確很有難度,我們得理解為什么必須先遍歷背包再遍歷物品,以及我們要區分題目是考察的我們是組合問題還是排列問題,就是看看有沒有順序要求即可,這就是我們今天的講解,我們明天見!?

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

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

相關文章

第41天-Python+Qt四屏播放器開發指南

一、技術選型與工具準備 核心庫: Pyqt5:Python標準GUI庫,構建用戶界面 os / sys:文件系統操作 開發環境: pip install pyqt5 最終效果與運行 import sys from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout # 添加缺失的布局管理器 from PyQt5.QtCore impor…

upload-labs通關筆記-第12關 文件上傳之白名單GET法

目錄 一、白名單過濾 二、%00截斷 1、%00截斷原理 2、空字符 3、截斷條件 &#xff08;1&#xff09;PHP版本 < 5.3.4 &#xff08;2&#xff09;magic_quotes_gpc配置為Off &#xff08;3&#xff09;代碼邏輯存在缺陷 三、源碼分析 1、代碼審計 &#xff08;1&…

Node.js數據抓取技術實戰示例

Node.js常用的庫有哪些呢&#xff1f;比如axios或者node-fetch用來發送HTTP請求&#xff0c;cheerio用來解析HTML&#xff0c;如果是動態網頁的話可能需要puppeteer這樣的無頭瀏覽器。這些工具的組合應該能滿足大部分需求。 然后&#xff0c;可能遇到的難點在哪里&#xff1f;…

數據結構(3)線性表-鏈表-單鏈表

我們學習過順序表時&#xff0c;一旦對頭部或中間的數據進行處理&#xff0c;由于物理結構的連續性&#xff0c;為了不覆蓋&#xff0c;都得移&#xff0c;就導致時間復雜度為O&#xff08;n&#xff09;&#xff0c;還有一個潛在的問題就是擴容&#xff0c;假如我們擴容前是10…

【Unity】DOTween的常用函數解釋

DOTween插件常用函數解釋 1.DOTween.To&#xff08;通用變化動畫&#xff09; 解釋&#xff1a;將某一個值在一定的時間內變化到另一個值&#xff08;通用的函數&#xff09;&#xff0c;可用于大部分的動畫變化 使用示例&#xff1a; using UnityEngine; using DG.Tweenin…

數據結構測試模擬題(1)

1、約瑟夫問題 #include<bits/stdc.h> using namespace std; const int N25; int e[N],ne[N],head-1,idx1; int n,m; void add_to_head(int x){e[idx]x;ne[idx]head;headidx; } void add(int k,int x){e[idx]x;ne[idx]ne[k];ne[k]idx; } int main(){cin>>n>>…

Helm配置之為特定Deployment配置特定Docker倉庫(覆蓋全局配置)

文章目錄 Helm配置之為特定Deployment配置特定Docker倉庫(覆蓋全局配置)需求方法1:使用Helm覆蓋值方法2: 在Lens中臨時修改Deployment配置步驟 1: 創建 Docker Registry Secret步驟 2: 在 Deployment 中引用 Secret參考資料Helm配置之為特定Deployment配置特定Docker倉庫(覆…

BERT 作為Transformer的Encoder 為什么采用可學習的位置編碼

摘要 BERT 在位置編碼上與原始 Transformer 論文中的 sin/cos 公式不同&#xff0c;選擇了可學習&#xff08;learned&#xff09;的位置嵌入方案。本文將從 Transformer 原始位置編碼選項入手&#xff0c;分析 BERT 選擇 learned positional embeddings 的四大核心原因&#x…

【Linux 學習計劃】-- gcc、g++、動靜態庫鏈接

目錄 什么是gcc、g gcc、g 相關操作詳解 預處理、編譯、匯編、鏈接來源 動靜態鏈接是什么 結語 什么是gcc、g gcc、g其實就是編譯器&#xff0c;是幫助我們從.c或者.cc&#xff0c;.cpp文件編譯成可執行程序的 其中&#xff0c;我們如果要編譯c語言文件的話&#xff0c;…

前端讀取本地項目中 public/a.xlsx 文件中的數據 vue3

前端讀取本地項目中 public/a.xlsx 文件中的數據 vue3 項目中需要在 Vue3 項目中讀取 public/a.xlsx 文件&#xff0c;可以使用 fetch API 來獲取文件內容 一、安裝 xlsx 首先&#xff0c;你需要安裝 xlsx 庫&#xff1a; npm install xlsx二、在需要用的頁面里引入xlsx im…

MySQL:to many connections連接數過多

當你遇到 MySQL: Too many connections 錯誤時&#xff0c;意味著當前連接數已達到 MySQL 配置的最大限制。這通常是由于并發連接過多或連接未正確關閉導致的。 一、查看當前連接數 查看 MySQL 當前允許的最大連接數 SHOW VARIABLES LIKE max_connections;查看當前使用的最大…

2024年熱門AI趨勢及回顧

人工智能的崛起 2024 年可能會被銘記為人工智能不再是一種技術新奇事物&#xff0c;而是成為現實的一年。微軟、Salesforce 和 Intuit 等巨頭將人工智能融入主流企業解決方案&#xff1b;從文案寫作到數據分析&#xff0c;專門的人工智能應用程序和服務如雨后春筍般涌現&#…

LangFlow技術深度解析:可視化編排LangChain應用的新范式 -(2)流編輯器系統

Flow Editor System | langflow-ai/langflow | DeepWiki 流編輯器系統 相關源文件 流編輯器系統是 Langflow 的核心交互式組件&#xff0c;允許用戶直觀地創建、編輯和管理 LLM 驅動的應用程序。它提供了一個直觀的畫布&#xff0c;用戶可以在其中添加節點、將其與邊緣連接并…

驅動-定時-秒-字符設備

文章目錄 目的相關資料參考實驗驅動程序-timer_dev.c編譯文件-Makefile測試程序-timer.c分析 加載驅動-運行測試程序總結 目的 通過定時器timer_list、字符設備、規避競爭關系-原子操作&#xff0c;綜合運用 實現一個程序&#xff0c;加深之前知識的理解。 實現字符設備驅動框…

[Java實戰]Spring Boot整合Kafka:高吞吐量消息系統實戰(二十七)

[Java實戰]Spring Boot整合Kafka&#xff1a;高吞吐量消息系統實戰&#xff08;二十七&#xff09; 一、引言 Apache Kafka作為一款高吞吐量、低延遲的分布式消息隊列系統&#xff0c;廣泛應用于實時數據處理、日志收集和事件驅動架構。結合Spring Boot的自動化配置能力&…

Kotlin Multiplatform--04:經驗總結(持續更新)

Kotlin Multiplatform--04&#xff1a;經驗總結&#xff08;持續更新&#xff09; 引言 引言 本章用來記載筆者開發過程中的一些經驗總結 一、Ktor設置Header 在官方文檔中&#xff0c;想要設置Header的示例代碼如下&#xff1a; client.get("https://ktor.io&qu…

在 Ubuntu 系統中,將 JAR 包安裝為服務

在 Ubuntu 系統中&#xff0c;將 JAR 包安裝為服務可以通過 systemd 來實現。以下是詳細的操作步驟&#xff1a; 準備工作 確保 JAR 文件路徑和 Java 運行時環境已準備好。驗證 Java 是否可用&#xff1a; java -version創建 systemd 服務文件 systemd 的服務文件通常位于 …

電商項目-商品微服務-品牌管理微服務開發

一、功能分析 品牌管理微服務包括&#xff1a; &#xff08;1&#xff09;查詢全部列表數據 &#xff08;2&#xff09;根據ID查詢實體數據 &#xff08;3&#xff09;增加 &#xff08;4&#xff09;修改 &#xff08;5&#xff09;刪除 &#xff08;6&#xff09;分頁…

Spring Boot開發—— 整合Lucene構建輕量級毫秒級響應的全文檢索引擎

文章目錄 一、為什么選擇 Lucene?輕量級搜索的底層密碼二、核心原理:Lucene 的倒排索引2.1 倒排索引:速度之源2.2 段合并優化策略三、Spring Boot集成Lucene實戰3.1 依賴配置3.2 實體與索引設計3.3 核心索引服務(含異常處理)3.4 使用示例(測試類)四、高級優化技巧4.1 索…

SpringBootDay1|面試題

目錄 一、springboot框架 1、什么是springboot 2、Spring Boot的主要優點 3、springboot核心注解 4、定義banner&#xff08;springboot的logo&#xff09; 5、springboot配置文件 6、springboot 整合 jdbc 二、面試題 1&#xff09;springmvc的作用 ?編輯 2&#x…