C++算法學習心得八.動態規劃算法(6)

1.最長遞增子序列(300題)

題目描述:

給你一個整數數組 nums ,找到其中最長嚴格遞增子序列的長度。

子序列是由數組派生而來的序列,刪除(或不刪除)數組中的元素而不改變其余元素的順序。例如,[3,6,2,7] 是數組 [0,3,1,6,2,2,7] 的子序列。

示例 1:

  • 輸入:nums = [10,9,2,5,3,7,101,18]
  • 輸出:4
  • 解釋:最長遞增子序列是 [2,3,7,101],因此長度為 4 。

?dp[i]表示i之前包括i的以nums[i]結尾的最長遞增子序列的長度

if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);

注意這里不是要dp[i] 與 dp[j] + 1進行比較,而是我們要取dp[j] + 1的最大值

每一個i,對應的dp[i](即最長遞增子序列)起始大小至少都是1.

dp[i] 是有0到i-1各個位置的最長遞增子序列 推導而來,那么遍歷i一定是從前向后遍歷

j其實就是遍歷0到i-1,那么是從前到后,還是從后到前遍歷都無所謂,只要吧 0 到 i-1 的元素都遍歷了就行了。 所以默認習慣 從前向后遍歷。

class Solution {
public:int lengthOfLIS(vector<int>& nums) {if(nums.size() <= 1)return nums.size();vector<int>dp(nums.size(),1);int result = 0;for(int i = 1;i < nums.size();i++){for(int j = 0;j < i;j++){if(nums[j] < nums[i])dp[i] = max(dp[i],dp[j] + 1);}if(dp[i] > result)result = dp[i];}return result;}
};
  • 時間復雜度: O(n^2)
  • 空間復雜度: O(n)

2.最長連續遞增序列(674題)

題目描述:

給定一個未經排序的整數數組,找到最長且連續遞增的子序列,并返回該序列的長度。

連續遞增的子序列 可以由兩個下標 l 和 r(l < r)確定,如果對于每個 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是連續遞增子序列。

示例 1:

  • 輸入:nums = [1,3,5,4,7]
  • 輸出:3
  • 解釋:最長連續遞增序列是 [1,3,5], 長度為3。盡管 [1,3,5,7] 也是升序的子序列, 但它不是連續的,因為 5 和 7 在原數組里被 4 隔開。

dp[i]:以下標i為結尾的連續遞增的子序列長度為dp[i],

如果 nums[i] > nums[i - 1],那么以 i 為結尾的連續遞增的子序列長度 一定等于 以i - 1為結尾的連續遞增的子序列長度 + 1 。

即:dp[i] = dp[i - 1] + 1;

因為本題要求連續遞增子序列,所以就只要比較nums[i]與nums[i - 1],而不用去比較nums[j]與nums[i] (j是在0到i之間遍歷)。

既然不用j了,那么也不用兩層for循環,本題一層for循環就行,比較nums[i] 和 nums[i - 1]。

以下標i為結尾的連續遞增的子序列長度最少也應該是1,即就是nums[i]這一個元素。

所以dp[i]應該初始1;

?dp[i + 1]依賴dp[i],所以一定是從前向后遍歷。

class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {if(nums.size() == 0)return nums.size();vector<int>dp(nums.size(),1);int result = 1;for(int i = 1;i < nums.size();i++){if(nums[i] > nums[i - 1])dp[i] = dp[i - 1] + 1;if(dp[i] > result)result = dp[i];}return result;}
};
  • 時間復雜度:O(n)
  • 空間復雜度:O(n)

貪心算法:

遇到nums[i] > nums[i - 1]的情況,count就++,否則count為1,記錄count的最大值就可以了。

class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {if(nums.size() == 0)return nums.size();int result = 1;int count = 1;for(int i = 1;i < nums.size();i++){if(nums[i] > nums[i - 1]){count++;}else{count = 1;}if(count > result)result = count;}return result;}
};
  • 時間復雜度:O(n)
  • 空間復雜度:O(1)

3.最長重復子數組(718題)

題目描述:

給兩個整數數組?A?和?B?,返回兩個數組中公共的、長度最長的子數組的長度。

示例:

輸入:

  • A: [1,2,3,2,1]
  • B: [3,2,1,4,7]
  • 輸出:3
  • 解釋:長度最長的公共子數組是 [3, 2, 1] 。

?dp[i][j] :以下標i - 1為結尾的A,和以下標j - 1為結尾的B,最長重復子數組長度為dp[i][j]。 (特別注意: “以下標i - 1為結尾的A” 標明一定是 以A[i-1]為結尾的字符串 )

dp[i][j]的定義,dp[i][j]的狀態只能由dp[i - 1][j - 1]推導出來。

即當A[i - 1] 和B[j - 1]相等的時候,dp[i][j] = dp[i - 1][j - 1] + 1;

dp[i][0] 和dp[0][j]初始化為0

外層for循環遍歷A,內層for循環遍歷B。

class Solution {
public:int findLength(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>>dp(nums1.size() + 1,vector<int>(nums2.size() + 1,0));int result = 0;for(int i = 1;i <= nums1.size();i++){for(int j = 1;j <= nums2.size();j++){if(nums1[i - 1] == nums2[j - 1])dp[i][j] = dp[i - 1][j - 1] + 1;if(dp[i][j] > result)result = dp[i][j];}}return result;}
};
  • 時間復雜度:O(n × m),n 為A長度,m為B長度
  • 空間復雜度:O(n × m)

?4.最長公共子序列(1143題)

題目描述:

給定兩個字符串?text1 和?text2,返回這兩個字符串的最長公共子序列的長度。

一個字符串的?子序列?是指這樣一個新的字符串:它是由原字符串在不改變字符的相對順序的情況下刪除某些字符(也可以不刪除任何字符)后組成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。兩個字符串的「公共子序列」是這兩個字符串所共同擁有的子序列。

若這兩個字符串沒有公共子序列,則返回 0。

示例 1:

  • 輸入:text1 = "abcde", text2 = "ace"
  • 輸出:3
  • 解釋:最長公共子序列是 "ace",它的長度為 3。

dp[i][j]:長度為[0, i - 1]的字符串text1與長度為[0, j - 1]的字符串text2的最長公共子序列為dp[i][j]

text1[i - 1] 與 text2[j - 1]相同,text1[i - 1] 與 text2[j - 1]不相同

如果text1[i - 1] 與 text2[j - 1]相同,那么找到了一個公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;

如果text1[i - 1] 與 text2[j - 1]不相同,那就看看text1[0, i - 2]與text2[0, j - 1]的最長公共子序列 和 text1[0, i - 1]與text2[0, j - 2]的最長公共子序列,取最大的。

即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

dp[i][0] = 0;

同理dp[0][j]也是0。

從前向后,從上到下來遍歷這個矩陣。

dp[text1.size()][text2.size()]為最終結果

class Solution {
public:int longestCommonSubsequence(string text1, string text2) {vector<vector<int>>dp(text1.size()+1,vector<int>(text2.size()+1,0));for(int i = 1;i <= text1.size();i++){for(int j = 1;j <= text2.size();j++){if(text1[i - 1] == text2[j - 1]){dp[i][j] = dp[i - 1][j - 1] + 1;}else{dp[i][j] = max(dp[i - 1][j],dp[i][j - 1]);}}}return dp[text1.size()][text2.size()];}
};
  • 時間復雜度: O(n * m),其中 n 和 m 分別為 text1 和 text2 的長度
  • 空間復雜度: O(n * m)

?5.不相交的線(1035題)

題目描述:

在兩條獨立的水平線上按給定的順序寫下?nums1?和?nums2?中的整數。

現在,可以繪制一些連接兩個數字?nums1[i]?和?nums2[j]?的直線,這些直線需要同時滿足滿足:

  • ?nums1[i] == nums2[j]
  • 且繪制的直線不與任何其他連線(非水平線)相交。

請注意,連線即使在端點也不能相交:每個數字只能屬于一條連線。

以這種方法繪制線條,并返回可以繪制的最大連線數。

?

本題說是求繪制的最大連線數,其實就是求兩個字符串的最長公共子序列的長度?

class Solution {
public:int maxUncrossedLines(vector<int>& A, vector<int>& B) {vector<vector<int>> dp(A.size() + 1, vector<int>(B.size() + 1, 0));for (int i = 1; i <= A.size(); i++) {for (int j = 1; j <= B.size(); j++) {if (A[i - 1] == B[j - 1]) {dp[i][j] = dp[i - 1][j - 1] + 1;} else {dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[A.size()][B.size()];}
};
  • 時間復雜度: O(n * m)
  • 空間復雜度: O(n * m)

6.?最大子序和(53題)

題目描述:

給定一個整數數組 nums?,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。

示例:

  • 輸入: [-2,1,-3,4,-1,2,1,-5,4]
  • 輸出: 6
  • 解釋:?連續子數組?[4,-1,2,1] 的和最大,為?6。

?dp[i]:包括下標i(以nums[i]為結尾)的最大連續子序列和為dp[i]

dp[i]只有兩個方向可以推出來:

  • dp[i - 1] + nums[i],即:nums[i]加入當前連續子序列和
  • nums[i],即:從頭開始計算當前連續子序列和

一定是取最大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);

遞推公式可以看出來dp[i]是依賴于dp[i - 1]的狀態,dp[0]就是遞推公式的基礎。

dp[0]應該是多少呢?

根據dp[i]的定義,很明顯dp[0]應為nums[0]即dp[0] = nums[0]。

遞推公式中dp[i]依賴于dp[i - 1]的狀態,需要從前向后遍歷,在遞推公式的時候,可以直接選出最大的dp[i]

class Solution {
public:int maxSubArray(vector<int>& nums) {if(nums.size() == 0)return 0;vector<int>dp(nums.size(),0);//dp[i]表示包括i之前的最大連續子序列和dp[0] = nums[0];int result = dp[0];for(int i = 1;i < nums.size();i++){dp[i] = max(dp[i-1]+nums[i],nums[i]);//狀態轉移公式,舍棄前面和當前基礎上再繼續加和if(dp[i] > result)result = dp[i];//result 保存dp[i]的最大值}return result;}
};
  • 時間復雜度:O(n)
  • 空間復雜度:O(n)

總結:

?最長遞增子序列:給定一個序列,其內部順序是不定的,所以這里要求最大升序序列長度,那么先定義dp數組的含義dp[i]代表i之前包括i的以nums[i]結尾的最長遞增子序列的長度,進行初始化操作,dp[i]大小為數組大小,且都賦值1,因為設定是長度至少有1,遍歷順序需要雙循環來外層I是從1到nums.size(),內層循環從0到i進行遍歷,遞推公式:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);還要記得需要更新dp[i]的值if(dp[i] > result)result = dp[i];最后返回result即可

最長連續遞增序列:動態規劃:上一題基礎上,介紹dp[i]:以下標i為結尾的連續遞增的子序列長度為dp[i],如果 nums[i] > nums[i - 1],那么以 i 為結尾的連續遞增的子序列長度 一定等于 以i - 1為結尾的連續遞增的子序列長度 + 1。遞推公式:dp[i] = dp[i - 1] + 1,本題要求連續遞增子序列,所以就只要比較nums[i]與nums[i - 1],而不用去比較nums[j]與nums[i] (j是在0到i之間遍歷),貪心算法:遇到nums[i] > nums[i - 1]的情況,count就++,否則count為1,記錄count的最大值就可以了。

最長重復子數組:給定兩個數組,然后對這兩個數組求最大重復子數組,dp[i][j] :以下標i - 1為結尾的A,和以下標j - 1為結尾的B,最長重復子數組長度為dp[i][j],dp[i][j]的定義,dp[i][j]的狀態只能由dp[i - 1][j - 1]推導出來,遞推公式:A[i - 1] 和B[j - 1]相等的時候,dp[i][j] = dp[i - 1][j - 1] + 1,初始化:dp[i][0] 和dp[0][j]初始化為0,遍歷順序:外層for循環遍歷A,內層for循環遍歷B。

最長公共子序列:給定兩個字符串,但是呢需要求的子序列是不改變相對順序,且可以刪除字符,dp[i][j]:長度為[0, i - 1]的字符串text1與長度為[0, j - 1]的字符串text2的最長公共子序列為dp[i][j],text1[i - 1] 與 text2[j - 1]相同,text1[i - 1] 與 text2[j - 1]不相同,如果text1[i - 1] 與 text2[j - 1]相同,那么找到了一個公共元素,所以dp[i][j] = dp[i - 1][j - 1] + 1;如果text1[i - 1] 與 text2[j - 1]不相同,那就看看text1[0, i - 2]與text2[0, j - 1]的最長公共子序列 和 text1[0, i - 1]與text2[0, j - 2]的最長公共子序列,取最大的。即:dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

不相交的線:求繪制的最大連線數,其實就是求兩個字符串的最長公共子序列的長度?,整體代碼和上一個最長公共子序列流程一樣,想法也大致相同,只是換一些字母。

最大子序和:dp[i]:包括下標i(以nums[i]為結尾)的最大連續子序列和為dp[i],dp[i]只有兩個方向,一個是dp[i-1]+nums[i],還有從開始nums[i]開始,遞推公式:dp[i] = max(dp[i - 1] + nums[i], nums[i]),dp[0]應為nums[0]即dp[0] = nums[0],dp[i]依賴于dp[i - 1]的狀態,需要從前向后遍歷,在遞推公式的時候,可以直接選出最大的dp[i]。

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

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

相關文章

Redis分布式集群部署

目錄 一. 原理簡述 二. 集群配置??????? 2.1 環境準備 2.2 編譯安裝一個redis 2.3 創建集群 2.4 寫入數據測試 實驗一&#xff1a; 實驗二&#xff1a; 實驗三&#xff1a; 實驗四&#xff1a; 添加節點 自動分配槽位 提升節點為master&#xff1a; 實驗…

關于電商平臺分類||電商平臺商品分類接口|電商平臺商品數據

電商平臺 做電商&#xff0c;則要有電商平臺&#xff0c;一個為 企業 或 個人 提供網上交易洽談的平臺。. 企業電子商務平臺是建立在 Internet 網上進行商務活動的虛擬網絡空間和保障商務順利運營的管理環境&#xff1b;是協調、整合 信息流 、貨物流、 資金流 有序、關聯、高效…

會員信息一鍵同步!微盟與客如云聯手打造智能服務新體驗!

客戶介紹 某房地產開發有限公司&#xff0c;自成立以來一直深耕于房地產行業&#xff0c;憑借卓越的開發實力和前瞻性的市場眼光&#xff0c;成為了業界備受矚目的企業。多年來&#xff0c;該公司始終堅持“品質至上&#xff0c;客戶為先”的經營理念&#xff0c;致力于為客戶…

新一代Java框架Quarkus的性能優化與應用

新一代Java框架Quarkus的性能優化與應用 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 引言 隨著云原生技術的發展&#xff0c;Java開發者們對于構建輕量級、…

JavaScript 編程語言【 數據類型】過濾|排序|映射|迭代

文章目錄 將 border-left-width 轉換成 borderLeftWidth過濾范圍原位&#xff08;in place&#xff09;過濾范圍降序排列復制和排序數組創建一個可擴展的 calculator映射到 names映射到對象按年齡對用戶排序隨機排列數組獲取平均年齡數組去重從數組創建鍵&#xff08;值&#x…

掌握React與TypeScript:從零開始繪制中國地圖

最近我需要使用reactts繪制一個界面&#xff0c;里面需要以中國地圖的形式展示區塊鏈從2019-2024年這五年的備案以及注銷情況&#xff0c;所以研究了一下這方面的工作&#xff0c;初步有了一些成果&#xff0c;所以現在做一些分享&#xff0c;希望對大家有幫助&#xff01; 在這…

手把手搞定報名亞馬遜科技認證

引言 亞馬遜云科技認證考試為我們這些技術從業者提供了提升專業技能的機會。無論選擇線上還是線下考試&#xff0c;每種方式都有其獨特的優勢和挑戰。選擇合適的考試方式將幫助我們更好地展示自己的技術水平。以下是我對不同考試方式的優缺點介紹&#xff0c;以及各科目的考試…

【pytorch12】什么是梯度

說明 導數偏微分梯度 梯度&#xff1a;是一個向量&#xff0c;向量的每一個軸是每一個方向上的偏微分 梯度是有方向也有大小&#xff0c;梯度的方向代表函數在當前點的一個增長的方向&#xff0c;然后這個向量的長度代表了這個點增長的速率 藍色代表比較小的值&#xff0c;紅色…

七月論文審稿GPT第5版:拿我司七月的早期paper-7方面review數據集微調LLama 3

前言 llama 3出來后&#xff0c;為了通過paper-review的數據集微調3&#xff0c;有以下各種方式 不用任何框架 工具 技術&#xff0c;直接微調原生的llama 3&#xff0c;畢竟也有8k長度了 效果不期望有多高&#xff0c;純作為baseline通過PI&#xff0c;把llama 3的8K長度擴展…

基于Linux的云端垃圾分類助手

項目簡介 本項目旨在開發一個基于嵌入式系統的智能垃圾分類裝置。該裝置能夠通過串口通信、語音播報、網絡通信等多種方式&#xff0c;實現垃圾的自動識別和分類投放。系統采用多線程設計&#xff0c;確保各功能模塊高效并行工作。 項目功能 垃圾分類識別 系統使用攝像頭拍攝…

解密tar文件解壓的Java實現技術

解密tar文件解壓的Java實現技術 大家好&#xff0c;我是免費搭建查券返利機器人省錢賺傭金就用微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 引言 在日常的軟件開發和系統管理中&#xff0c;經常會遇到需要解壓縮文件的…

代碼隨想三刷動態規劃篇5

代碼隨想三刷動態規劃篇5 377. 組合總和 Ⅳ題目代碼 57. 爬樓梯&#xff08;第八期模擬筆試&#xff09;題目代碼 322. 零錢兌換題目代碼 279. 完全平方數題目代碼 377. 組合總和 Ⅳ 題目 鏈接 代碼 class Solution {public int combinationSum4(int[] nums, int target) {…

SM2的簽名值byte數組與ASN.1互轉

ASN.1抽象語言標記(Abstract Syntax Notation One) ASN.1是一種 ISO/ITU-T 標準,描述了一種對數據進行表示、編碼、傳輸和解碼的數據格式,它提供了一整套正規的格式用于描述對象的結構。 一、該結構的應用場景 例如在做待簽名的數字信封時,數字信封使用ASN.1封裝,這個時…

MySQL-行級鎖(行鎖、間隙鎖、臨鍵鎖)

文章目錄 1、介紹2、查看意向鎖及行鎖的加鎖情況3、行鎖的演示3.1、普通的select語句&#xff0c;執行時&#xff0c;不會加鎖3.2、select * from stu where id 1 lock in share mode;3.3、共享鎖與共享鎖之間兼容。3.4、共享鎖與排他鎖之間互斥。3.5、排它鎖與排他鎖之間互斥3…

論文調研_Awesome-Binary-Similarity

0. 概述 對 Awesome-Binary-Similarity 中列出的論文進行調研,重點總結這些論文的研究動機與未來研究方向。 1. 調研內容 論文名稱發表時間發表期刊期刊等級研究單位BinaryAI: Binary Software Composition Analysis via Intelligent Binary Source Code Matching2024年ICSE…

每日一題---OJ題:分隔鏈表

片頭 嗨&#xff01;小伙伴們&#xff0c;大家好&#xff01;今天我們一起來看看這道題----分隔鏈表 emmmm&#xff0c;這道題&#xff0c;看描述應該不算太難&#xff0c;我們一起來畫一畫圖唄&#xff01; 題目讀懂了&#xff0c;那么如何破解這道題呢&#xff1f; 思路&…

microApp vue3+vite+ts 子應用接入改造

公司做了一個平臺,使用的是microApp,需要把現有的一些系統作為子系統改造一下接入這個平臺,所以下面我說的都是子應用的改造,vue2的改造比較簡單,主要的vue3+vite+ts的改造。 參考官網 1、設置跨應用支持 vite默認開啟跨域支持,不需要額外配置。 2、注冊卸載函數 // …

nand flash spec

nand flash簡介 nand flash是一種非易失性存儲器。它具有高存儲密度、低成本和高耐用性的特點。 nand flash的特性是非易失性&#xff0c;即在電源關閉的情況下&#xff0c;數據仍然保留。 nand flash的存儲單元由浮動柵極晶體管組成&#xff0c;每個存儲單元可以存儲一位或多…

短視頻世界對我溫柔以待:成都柏煜文化傳媒有限公司

短視頻世界對我溫柔以待 在繁忙的都市生活中&#xff0c;每個人都在為生活奔波&#xff0c;為夢想努力。而在這個快節奏的時代里&#xff0c;短視頻如同一股清流&#xff0c;以其獨特的魅力&#xff0c;為我帶來了片刻的寧靜與溫柔。它像是一個無聲的朋友&#xff0c;在我疲憊…

(必看圖文)Hadoop集群安裝及MapReduce應用(手把手詳解版)

前言 隨著大數據時代的到來&#xff0c;處理和分析海量數據已成為企業和科研機構不可或缺的能力。Hadoop&#xff0c;作為開源的分布式計算平臺&#xff0c;因其強大的數據處理能力和良好的可擴展性&#xff0c;成為大數據處理領域的佼佼者。本圖文教程旨在幫助讀者理解Hadoop集…