DP:子數組問題

文章目錄

  • 引言
  • 子數組問題介紹
  • 動態規劃的基本概念
  • 具體問題的解決方法
  • 動態規劃解法:
  • 關于子數組問題的幾個題
    • 1.最大子數組和
    • 2.環形子數組的最大和
    • 3.乘積最大子數組
    • 4.乘積為正數的最長子數組長度
    • 5.等差數列劃分
  • 總結

在這里插入圖片描述

引言

介紹動態規劃(DP)在解決子數組問題上的重要性,以及本文的目的——通過具體問題的分析和代碼示例,幫助讀者理解如何用DP解決子數組問題。

子數組問題介紹

簡要介紹什么是子數組問題,以及這些問題在實際應用中的重要性。例如,最大子數組和問題、最長遞增子數組問題等。

動態規劃的基本概念

解釋動態規劃的基本思想:通過將問題分解為子問題,保存子問題的解來避免重復計算,從而提高算法效率。可以簡單介紹狀態、狀態轉移方程和初始條件等基本概念。

具體問題的解決方法

最大子數組和問題(Maximum Subarray Sum)
問題描述:
給定一個整數數組,找出和最大的連續子數組,并返回其最大和。

動態規劃解法:

定義狀態:dp[i]表示以第i個元素結尾的最大子數組和。
狀態轉移方程:dp[i] = max(nums[i], dp[i-1] + nums[i])
即對于第i個元素,最大子數組和要么是自己,要么是前一個元素的最大子數組和加上自己。
初始狀態:dp[0] = nums[0]
結果:max(dp),即所有dp[i]中的最大值。

關于子數組問題的幾個題

1.最大子數組和

題目鏈接
題目:

在這里插入圖片描述

樣例輸出和輸入:

在這里插入圖片描述

題目要求很簡單,就是求出 最長的子數組的和,這個和有一個要求就是和最大。
算法原理:
狀態表示:dp[i]表示以i位置為結尾時所有子數組的和中最大的那個。
狀態轉移方程:
分析:到達i位置時i位置最長的子數組的和應該等于i-1位置的最長子數組的和加上當前i位置的值,還有一種情況:單獨分析,就是當前位置的數就是一個子數組,長度為1,所以,dp[i]=max(dp[i-1]+nums[i],nums[i])
代碼展示:

class Solution {
public:int maxSubArray(vector<int>& nums){int n = nums.size();vector<int> dp(n);dp[0] = nums[0];for (int i = 1;i < n;i++){dp[i] = max(dp[i - 1] + nums[i], nums[i]);}int  Max = -0x3f3f3f3f;for (int i = 0;i < n;i++){Max = max(dp[i], Max);}return Max;}
};

運行結果:
在這里插入圖片描述

2.環形子數組的最大和

題目鏈接
題目:

在這里插入圖片描述

樣例輸出和輸入:

在這里插入圖片描述

這道題在第一道題的基礎上加了一個條件,就是這是個環形數組頭和尾是相連的。也讓我們求子數組中和最大的那個。
算法原理:
狀態表示:分析:明顯這道題一個狀態是表示不了的,因為這個子數組可能連續也可能不連續,由于求的最大的值,所以第一種情況:當子數組在中間時最大,還有一種情況,子數組在兩邊時不連續的時候最大 ,當不連續的時候 最大,也就是中間的最小。這兩種狀態分別為f[i]和g[i]。
在這里插入圖片描述
狀態轉移方程:先分析中間最大的時候的狀態,當到達i位置的時候i位置的最大的子數組的和就是前一個位置i-1的位置的最大的子數組的和加上當前i位置的值,還有一種情況就是i位置自身成一個長度為1的數組。f[i] = max(f[i - 1] + nums[i-1], nums[i-1]),g[i]也同理,g[i]為當前位置的子數組中最小的那個 子數組的和,所以i位置的子數組和的最小等于前一個位置的子數組和的最小,加上當前位置,g[i - 1] + nums[i-1]最后還要取一個min,g[i] = min(g[i - 1] + nums[i-1], nums[i-1])

代碼展示:

class Solution {
public:int maxSubarraySumCircular(vector<int>& nums){int n = nums.size();vector<int> f(n + 1), g(n + 1);int sum = 0;int fmax = INT_MIN;int gmin = INT_MAX;for (int i = 1;i <= n;i++){f[i] = max(f[i - 1] + nums[i-1], nums[i-1]);fmax = max(f[i], fmax);g[i] = min(g[i - 1] + nums[i-1], nums[i-1]);gmin = min(gmin, g[i]);sum += nums[i - 1];}return sum == gmin ? fmax : max(fmax, sum - gmin);}
};

運行結果:
在這里插入圖片描述

3.乘積最大子數組

題目鏈接
題目:

在這里插入圖片描述

樣例輸出和輸入:

在這里插入圖片描述

這道題的題意和前兩道題也大差不差,就是讓我們求最大乘積的子數組的乘積。
算法原理:
狀態表示:這道題還是需要兩個狀態,因為有負數情況,不一定是正數乘正數才是最大的,兩個負數相乘也 有可能是最大的。f[i]表示以i位置為結尾的子數組中的最大乘積的那個,g[i]表示以i位置為結尾的子數組中最小的乘積的那個。
狀態轉移方程:首先分析f[i]這個狀態,這個狀態有三個子狀態,第一種狀態是i位置是負數時,所以負數應乘上最小的才是最大的,還有一種狀態就是當前位置是正數,所以當前位置應該乘上前一個位置中最大的那個子數組的乘積。還有一個情況就是單獨成為一個子數組。
在這里插入圖片描述
max(nums[i - 1], max(f[i - 1] * nums[i - 1], g[i - 1] * nums[i - 1]))
g[i]的狀態轉移方程也可以用類似的方法進行分析:min(nums[i - 1], min(f[i - 1] * nums[i - 1], g[i - 1] * nums[i - 1]))

代碼展示:

class Solution {
public:int maxProduct(vector<int>& nums){int n = nums.size();vector<double> f(n + 1), g(n + 1);//f是最大的,g是最小的g[0] = 1, f[0] = 1;double ret = INT_MIN;for (int i = 1;i <= n;i++){double x = nums[i - 1], y = f[i - 1] * nums[i - 1], z = g[i - 1] * nums[i - 1];f[i] = max(x, max(y, z));g[i] = min(x, min(y, z));ret = max(f[i], ret);}return ret;}
};

運行結果:
在這里插入圖片描述

4.乘積為正數的最長子數組長度

題目鏈接
題目:

在這里插入圖片描述

樣例輸出和輸入:

在這里插入圖片描述

這道題要求的是乘積是正數的子數組總長度最長的那個子數組的長度。
算法原理:
狀態表示:由于兩個負數相乘也是正數,所以狀態表示的時候我們也要記錄負數的狀態,f[i]表示以i位置為結尾的所有子數組中乘積是正數的最長的子數組的長度,g[i]]是以i位置為結尾的子數組中乘積為負數的最長子數組的長度。
狀態轉移方程:需要判斷i位置的值是正數還是負數,如果是負數的話就是就需要用前一個位置的負數子數組的最長的那個加一,也就是g[i-1]+1但是前i-1個有可能沒有小于零的,所以這里f[i]是有可能是零的,所以這里需要判斷一下i-1位置時的g[i-1]的值,當當前值大于零的時候f[i]就等于 前一個位置的f[i-1]+1,同理負數的最長子數組也可以分析出來,狀態轉移方程:這是大于零的兩種狀態的情況:g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1f[i] = f[i - 1] + 1小于零的兩種狀態的情況:f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1g[i] = f[i - 1] + 1

代碼展示:

class Solution {
public:int getMaxLen(vector<int>& nums) {int n = nums.size();if (n == 1){return nums[0] > 0;}vector<int> f(n), g(n);f[0] = nums[0] > 0, g[0] = nums[0] < 0;int fmax = 0;for (int i = 1;i < n;i++){if (nums[i] > 0){f[i] = f[i - 1] + 1;g[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;fmax = max(f[i], fmax);}else if (nums[i] < 0){f[i] = g[i - 1] == 0 ? 0 : g[i - 1] + 1;g[i] = f[i - 1] + 1;fmax = max(f[i], fmax);}}return fmax;}
};

運行結果:
在這里插入圖片描述

5.等差數列劃分

題目鏈接
題目:

在這里插入圖片描述

樣例輸出和輸入:

在這里插入圖片描述

這道題題意很簡單,就是讓我們求所有能構成等差數列的子數組的總和
算法原理:
等差數列性質:2a=c+ba為等差中項。
狀態表示:dp[i]為以i位置為結尾的所有子數組中的等差數列的個數。
狀態轉移方程:先判斷i位置的前兩個位置是否 滿足上述的等差數列的性質:如果滿足則dp[i]=dp[i - 1] + 1因為滿足,所以dp[i-1]位置需要算上,但是又多了一個子數組,這個子數組 就是滿足的那個三個數的子數組。不滿足的話,dp[i]直接就是0.
代碼展示:

class Solution {
public:int numberOfArithmeticSlices(vector<int>& nums) {int n = nums.size();if (n < 3){return  0;}vector<int>  dp(n);dp[0] = 0, dp[1] = 0;int count = 0;for (int i = 2;i < n;i++){dp[i] = nums[i] + nums[i - 2] == 2 * nums[i - 1] ? dp[i - 1] + 1 : 0;}for(int i=0;i<n;i++){count+=dp[i];}return count;}
};

運行結果:
在這里插入圖片描述

總結

通過本文的介紹,我們詳細探討了動態規劃在解決子數組問題中的應用,具體分析了最大子數組和問題和最長遞增子數組問題。這些問題在實際生活中的數據處理、優化等場景中有著廣泛的應用。動態規劃通過將問題分解為子問題,保存子問題的解,避免了重復計算,從而大大提高了算法的效率。

在學習和應用動態規劃的過程中,我們需要明確狀態、狀態轉移方程和初始條件。通過練習具體問題,我們可以更深入地理解動態規劃的思想和方法。無論是最大子數組和問題還是最長遞增子數組問題,掌握了動態規劃的基本原理后,我們可以更靈活地應對其他類似的問題。

希望這篇文章能幫助你更好地理解動態規劃在子數組問題中的應用。如果你有任何問題或建議,歡迎在評論區留言,我們將盡力為你解答。祝你在學習動態規劃和解決實際問題的過程中取得更多的進步!

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

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

相關文章

音視頻開發31 FFmpeg 編碼- avcodec_find_encoder和avcodec_find_encoder_by_name

avcodec_find_encoder /** * Find a registered encoder with a matching codec ID. * * param id AVCodecID of the requested encoder * return An encoder if one was found, NULL otherwise. */ AVCodec *avcodec_find_encoder(enum AVCodecID id); 那么這個 AVCodec…

14分Top刊NC代碼開源|NSCLC單細胞+空轉腫瘤微環境分析

說在前面 說起肺癌真的過去回憶歷歷在目&#xff0c;小編畢業后職業生涯的第一個項目——非小細胞肺癌預后有效靶點篩選。當時肝的是轉錄組預后建模篩選。 做研發其實要求是遠遠高于發文章的&#xff0c;文章投不出去就降分&#xff0c;加工作量&#xff0c;做藥要是爛尾或者…

2024年7月1日 (周一) 葉子游戲新聞

老板鍵工具來喚去: 它可以為常用程序自定義快捷鍵&#xff0c;實現一鍵喚起、一鍵隱藏的 Windows 工具&#xff0c;并且支持窗口動態綁定快捷鍵&#xff08;無需設置自動實現&#xff09;。 喜馬拉雅下載工具: 字面意思 《星刃》早期概念圖分享 末世破敗環境推主Genki分享了《星…

Spire.PDF for .NET【文檔操作】演示:在 PDF 中創建目錄 (TOC)

目錄在增強文檔的可讀性和可導航性方面起著至關重要的作用。它為讀者提供了文檔結構的清晰概述&#xff0c;使他們能夠快速找到并訪問他們感興趣的特定部分或信息。這對于較長的文檔&#xff08;例如報告、書籍或學術論文&#xff09;尤其有價值&#xff0c;因為讀者可能需要多…

部署calico網絡插件

部署calico網絡插件 之前的k8s環境中主要使用了flannel作為網絡插件&#xff0c;這次改用calico。calico支持多種安裝方式&#xff0c;以下是具體的操作步驟。 1. 準備工作 環境信息 # 系統信息 rootmaster1:~# cat /etc/issue Ubuntu 24.04 LTS \n \lrootmaster1:~# uname…

MyBatisPlus 常用的注解 表映射 主鍵映射 字段映射

介紹 官網&#xff1a;https://baomidou.com/reference/annotation/ 指定映射表 實體類使用駝峰命名&#xff0c;表名應為xx_xxx等格式這樣才可以映射&#xff0c;但是實際開發過程中可能不一致就可以使用該方法處理。 Data TableName("employee_235") //映射的表…

求質數題目

//需求:鍵盤錄入一個正整數x&#xff0c;判斷該整數是否為一個質數。 //質數: //如果一個整數只能被1和本身整除&#xff0c;那么這個數就是質數。否則這個數叫做合數 package Base_se.Base_701;import java.util.Scanner;/*** author gyf* ClassName test* Date 2024/7/1 19:…

Linux啟動elasticsearch,提示權限不夠

Linux啟動elasticsearch&#xff0c;提示權限不夠&#xff0c;如下圖所示&#xff1a; 解決辦法&#xff1a; 設置文件所有者&#xff0c;即使用戶由權限訪問文件 sudo chown -R 用戶名[:新組] ./elasticsearch-8.10.4 //切換到elasticsearch-8.10.4目錄同級 chown詳細格式…

銀行家算法-操作系統中避免死鎖的最著名算法

背景 有很多文章都會介紹銀行家算法。在百度和CSDN上搜一搜能搜出很多來。很多同學會覺得這個算法很深奧&#xff0c;有些文章寫的又很復雜&#xff0c;其實真的很簡單。這里簡單記錄一下基本原理&#xff0c;然后大家再配合其他文章看&#xff0c;就能加深理解。 算法原理 …

LLaVA1.5訓練數據和時間分析

LLaVA的PT+SFT訓練_llava sft-CSDN博客文章瀏覽閱讀379次。這個階段,使用8個A100(80G)訓練LLaVA-v1.5-13B大約需要20h。全量微調,非lora跑不起來啊,以前一直用swift,llama-factory這種框架式的代碼庫,但用原作者開源的代碼也是有很多好處的。在這個階段,使用 8 個 A100(…

Oracle中 ROW_NUMBER()的語法及在對應不同需求下應如何使用

Oracle數據庫中的ROW_NUMBER()函數是一個窗口函數&#xff0c;它為查詢結果集中的每一行分配一個唯一的序號。這個函數在數據分析、分頁查詢、數據去重和排名問題等方面非常有用。ROW_NUMBER()函數的語法如下&#xff1a; ROW_NUMBER() OVER ( [ PARTITION BY column ] ORDER …

3.用戶程序與驅動交互

驅動程序請使用第二章https://blog.csdn.net/chenhequanlalala/article/details/140034424 用戶app與驅動交互最常見的做法是insmod驅動后&#xff0c;生成一個設備節點&#xff0c;app通過open&#xff0c;read等系統調用去操作這個設備節點&#xff0c;這里先用mknode命令調…

64.WEB滲透測試-信息收集- WAF、框架組件識別(4)

免責聲明&#xff1a;內容僅供學習參考&#xff0c;請合法利用知識&#xff0c;禁止進行違法犯罪活動&#xff01; 內容參考于&#xff1a; 易錦網校會員專享課 上一個內容&#xff1a;63.WEB滲透測試-信息收集- WAF、框架組件識別&#xff08;3&#xff09;-CSDN博客 我們在…

【FedMut】Generalized Federated Learning via Stochastic Mutation

基于隨機變異的泛化聯邦學習 來源&#xff1a;AAAI2024 Abstract 問題&#xff1a; FedAvg 將相同的全局模型派發給客戶端進行本地訓練&#xff0c;容易陷入尖銳解&#xff0c;導致訓練出性能低下的全局模型 提出 FedMut&#xff1a; 本文提出了一種名為 FedMut 的新型FL方法…

2024免費的股票數據接口API

滄海數據 # Restful API https://tsanghi.com/api/fin/stock/{exchange_code}/realtime?token5dbb47113a4a43a6be1755673ce854db&ticker{ticker} 數據來源&#xff1a;滄海數據 請求方式&#xff1a;Get 數據格式&#xff1a;標準Json格式[{},...{}]

如何借用物聯網快速實現高標準農田信息化

如何借用物聯網快速實現高標準農田信息化 高標準農田信息化&#xff0c;作為現代農業發展的重要基石&#xff0c;是指在建設高產、穩產、節水、環保的農田基礎上&#xff0c;深度融合現代信息技術&#xff0c;實現農田管理的精準化、智能化和高效化。物聯網&#xff08;Intern…

vue3+ts實現計算兩個字符串的相似度

在TypeScript中&#xff0c;可以使用Levenshtein萊文斯坦距離算法來精確匹配兩個字符串的相似度百分比。Levenshtein距離是指兩個字符串之間&#xff0c;由一個轉換成另一個所需的最少編輯操作次數&#xff0c;這里的編輯操作包括插入、刪除、替換。 /*** Levenshtein距離算法…

Linux Static calls機制

文章目錄 前言一、簡介二、Background: indirect calls, Spectre, and retpolines2.1 Indirect calls2.2 Spectre (v2)2.3 RetpolinesConsequences 2.4 Static callsHow it works 三、其他參考資料 前言 Linux內核5.10內核版本引入新特性&#xff1a;Static calls。 Static c…

JAVA各版本-安裝教程

目錄 Java安裝包下載 Java安裝步驟 Java環境配置 Java安裝包下載 到Oracle官網下載自己需要的版本 Oracle Java下載&#xff1a;Java Archive | Oracle Hong Kong SAR, PRC 下拉選擇自己需要的版本&#xff08;本教程以Windows環境下&#xff0c;JAVA11為例&#xff09; 注…

C++初學者指南-3.自定義類型(第一部分)-指針

C初學者指南-3.自定義類型(第一部分)-指針 文章目錄 C初學者指南-3.自定義類型(第一部分)-指針1.為什么我們需要它們&#xff1f;2.T 類型的對象指針原始指針&#xff1a;T * 智能指針(C11) 3.操作符地址操作符 &解引用運算符 *成員訪問操作符 ->語法重定向 4.nullptr (…