女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

動態規劃:8行代碼搞定最大子數組和問題

算法與數據結構 ? 來源:碼農的荒島求生 ? 作者:碼農的荒島求生 ? 2022-04-01 10:24 ? 次閱讀

鐵子們,我是小風哥,你也可以叫我島主

今天給大家帶來一道極其經典的題目,叫做最大和子數組,給定一個數組,找到其中的一個連續子數組,其和最大。

示例:

輸入:nums=[-2,1,-3,4,-1,2,1,-5,4]
輸出:6
解釋:子數組[4,-1,2,1]的和為6,其它任何連續的子數組和不超過6.

想一想該怎樣解決這個問題。

如果你一時想不到解法可以從暴利解法開始。

暴力求解

這種解法最簡單,我們把所有子數組找出來,然后依次計算其和,找出一個最大的出來,比如給定數組[1,2,3],那么我們能找出子數組:[1],[2],[3],[1,2],[2,3],[1,2,3],很顯然這里和最大的子數組為[1,2,3],其值為6。

intsum(vector&nums,intb,inte){
intres=0;
for(;b<=?e;?b++)?{
????????res?+=?nums[b];
????}
????returnres;
}
intmaxSubArray(vector&nums){
intsize=nums.size();
intres=0x80000000;
for(inti=0;ifor(intj=i;jreturnres;
}

這種解法最簡單,該算法的時間復雜度為O(n^3),其中找出所有子數組的時間復雜度為O(n^2),計算每個子數組的和的時間復雜度為O(n),因此其時間復雜度為O(n^3)。

讓我們再來看一下這個過程,這里的問題在于計算每個子數組的和時有很多重復計算,比如我們知道了子數組[1,2]的和后再計算數組[1,2,3]的值時完全可以利用子數組[1,2]的計算結果而無需從頭到尾再算一遍,也就是說我們可以利用上一步的計算結果,這本身就是動態規劃的思想。

8589ba58-b15c-11ec-aa7f-dac502259ad0.png

基于該思想我們可以對上述代碼簡單改造一下:

intmaxSubArray(vector&nums){
intsize=nums.size();
intres=0x80000000;
for(inti=0;ifor(intj=i+1;jreturnres;
}

看到了吧,代碼不但更簡潔,而且運行速度更快,該算法的時間復雜度為O(n^2),比第一種解法高了很多。

還有沒有進一步提高的空間呢?

答案是肯定的。

分而治之

我們在之前的文章中說過,分治也是一種非常強大的思想,具體應該這里的話我們可以把整個數組一分為二,然后子數組也一分為二,不斷劃分下去就像這樣:

859b978c-b15c-11ec-aa7f-dac502259ad0.png

然后呢?

然后問題才真正開始有趣起來,注意,當我們劃分到最下層的時候,也就是不可再劃分時會得到兩個數組元素,比如對于數組[1,2]會劃分出[1]與[2],此時[1]與[2]不可再劃分,那么對于子問題[1,2],其最大子數組的和為max(1+2, 1,2),也就是說要么是左半部分的元素值、要么是右半部分的元素值、要么是兩個元素的和,就這樣我們得到了最后兩層的答案:

85bb2606-b15c-11ec-aa7f-dac502259ad0.png

假設對于數組[1,2,3,4],一次劃分后得到了[1,2]與[3,4],用上面的方法我們可以分別知道這兩個問題的最大子數組和,我們怎樣利用上述的答案來解決更大的問題,也就是[1,2,3,4]呢?

很顯然,對于[1,2,3,4]來說,最大子數組的和要么來自左半部分、要么來自右半部分、要么來自中間部分——也就是包含2和3,其中左半部分和右半部分的答案我們有了,那么中間部分的最大和該是多少呢?

其實這個問題很簡單,我們從中間開始往兩邊不斷累加,然后記下這個過程的最大值,比如對于[1,-2,3,-4,5],我們從中間的3開始先往左邊累加和是:{1+(-2)+3, (-2)+3, 3}也就是{2,1,3},因此我們以中間數字為結尾的最大子數組和為3:

85ce2bde-b15c-11ec-aa7f-dac502259ad0.png

另一邊也是同樣的道理,只不過這次是以中間數字為起點向右累加:

85e0d090-b15c-11ec-aa7f-dac502259ad0.png

然后這三種情況中取一個最大值即可,這樣我們就基于子問題解決了更大的問題:

85f977a8-b15c-11ec-aa7f-dac502259ad0.png

此后的道理一樣,最終我們得到了整個問題的解。

根據上面的分析就可以寫代碼了:

intgetMaxSum(vector&nums,intb,inte){
if(b==e)returnnums[b];
if(b==e-1)returnmax(nums[b],max(nums[e],nums[b]+nums[e]));
intm=(b+e)/2;
intmaxleft=nums[m];
intmaxright=nums[m];
intsum=nums[m];

for(inti=m+1;i<=?e;?i++)?{
????????sum?+=?nums[i];
????????maxright?=?max(maxright,?sum);
????}

????sum?=?nums[m];
????for(inti=m-1;i>=b;i--){
sum+=nums[i];
maxleft=max(maxleft,sum);
}
returnmax(getMaxSum(nums,b,m-1),max(getMaxSum(nums,m+1,e),maxleft+maxright-nums[m]));
}
intmaxSubArray(vector&nums){
returngetMaxSum(nums,0,nums.size()-1);
}

上述這段代碼的時間復雜度為O(NlogN)比第二種方法又提高了很多。

動態規劃

實際上這個問題還有另一種更妙的解決方法,我們令dp(i)表示以元素A[i]為結尾的最大子數組的和,那么根據這一定義則有:

860dadd6-b15c-11ec-aa7f-dac502259ad0.png

這是很顯然的,注意dp(i)的定義,是以元素A[i]為結尾的最大子數組的和,因此dp(i)的值要么就是A[i]連接上之前的一個子數組,那么不鏈接任何數組,那么最終的結果一定是以某個元素為結尾的子數組,因此我們從所有的dp(i)中取一個最大的就好了,依賴子問題解決當前問題的解就是所謂的動態規劃。

有了這些分析,代碼非常簡單:

intmaxSubArray(vector&nums){
intsize=nums.size();
vectordp(size,0);
intres=dp[0]=nums[0];
for(inti=1;ireturnres;
}

這段代碼簡單到讓人難以置信,只有8行代碼,你甚至可能會懷疑這段代碼的正確性,但它的確是沒有任何問題的,而且這段代碼的時間復雜度只有O(N),這段代碼既簡單運行速度又快,這大概就是算法的魅力吧。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4887

    瀏覽量

    70264
  • 數組
    +關注

    關注

    1

    文章

    419

    瀏覽量

    26373

原文標題:動態規劃:8行代碼搞定最大子數組和問題

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數據結構】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    二維數組指定條件刪除指定,請教

    數組1的第一列進行條件判斷,如果小于20,刪除所在行,最終需要得到數組2
    發表于 05-13 08:11

    8通道LED陽極驅動電路——AiP3318

    8通道LED陽極驅動電路——AiP3318
    的頭像 發表于 02-18 09:49 ?442次閱讀
    <b class='flag-5'>8</b>通道LED陽極<b class='flag-5'>行</b>驅動電路——AiP3318

    Labivew 實現鼠標在數組中選中元素時,精準的顯示所在位置的、列值方法

    在項目開發中,遇到一個布爾的二維數組輸入控件,選中數組元素并索引出行列的操作,試過其他大佬的方法,不是特別精準,,嘗試一下還可以,分享給需要的朋友 *附件:選中二維數組元素并索引所在的
    發表于 12-21 18:07

    數組的下標為什么可以是負數

    最近有同學發來這樣一段代碼,并提出一個問題,數組的下標為什么可以是負數? ? ? #include int main(){ const char *s = "helloworld"; const
    的頭像 發表于 12-20 11:18 ?442次閱讀

    北汽集團戰略投資小馬智7035萬美元

    日前,北汽集團戰略投資小馬智7035萬美元,小馬智于11月27日在美國納斯達克掛牌上市(股票代碼“PONY”),公開發行定價為13美元/ADS,融資額達2.99億美元,成為今年以來美股自動駕駛領域
    的頭像 發表于 12-02 11:46 ?716次閱讀

    自動駕駛企業小馬智登陸納斯達克

    近日,小馬智正式在納斯達克掛牌上市,股票代碼“PONY”,公開發行定價為13美元/ADS,融資額達2.99億美元,成為今年以來美股自動駕駛領域最大規模IPO。
    的頭像 發表于 11-29 09:59 ?457次閱讀

    小馬智納斯達克掛牌上市

    近日,小馬智正式在納斯達克掛牌上市,股票代碼“PONY”,成為Robotaxi第一股。在擴大發行規模后,若承銷商的超額配售權悉數行使,小馬智行將以每股13美元的發行區間價上限發行總計2300萬股
    的頭像 發表于 11-28 09:55 ?504次閱讀

    數組名之間可以直接賦值嗎

    數組之間的賦值能不能直接使用等于號?比如這樣的代碼。 int main(){ int a[5] = {1, 2, 3, 4, 5}; int b[5] = {0}; b = a
    的頭像 發表于 11-26 11:23 ?512次閱讀

    指針數組和二維數組有沒有區別

    指針數組和二維數組有沒有區別?比如這樣的兩個代碼。 int main(){ char *s1[] = { "hello", "world", "total" }; char s2[][6
    的頭像 發表于 11-24 11:12 ?483次閱讀

    C語言數組應用計算機導論A第6講:數組

    C語言數組應用計算機導論A第6講:數組
    發表于 11-20 15:33 ?0次下載

    8通道3.2A輸出電流消隱可調共陰驅動芯片SM5188詳解

    8通道3.2A輸出電流消隱可調共陰驅動芯片 通道數與電流輸出: 提供8通道的驅動能力,可以同時控制8路LED或其他電子設備的運行。 每個通道的最大
    的頭像 發表于 11-20 14:21 ?701次閱讀
    <b class='flag-5'>8</b>通道3.2A輸出電流消隱可調共陰<b class='flag-5'>行</b>驅動芯片SM5188詳解

    多臺倉儲AGV協作全局路徑規劃算法的研究

    多AGV動態路徑規劃需解決沖突避免,核心在整體協調最優。規劃時考慮道路設計、擁堵、最短路徑和交通管制,用A*算法避免重復路徑和轉彎,同時需交通管制防相撞。創新響應需求是關鍵,良好路徑規劃
    的頭像 發表于 10-28 17:38 ?725次閱讀
    多臺倉儲AGV協作全局路徑<b class='flag-5'>規劃</b>算法的研究

    labview按讀取二維數組之后再按讀取順序重新組成二維數組如何實現?

    labview用了index Array按索引一行行讀取二維數組之后想再按讀取順序重新組成一個二維數組如何實現,即第一次讀取的作為第一,第二次讀取的作為第二
    發表于 10-25 21:06

    labview字符串數組轉化為數值數組

    在LabVIEW中,將字符串數組轉換為數值數組是一項常見的任務,尤其是在處理數據采集、信號處理或用戶輸入時。 1. 理解LabVIEW的數據類型 在開始之前,了解LabVIEW中的數據類型是非
    的頭像 發表于 09-04 17:47 ?4887次閱讀

    面試常考+1:函數指針與指針函數、數組指針與指針數組

    在嵌入式開發領域,函數指針、指針函數、數組指針和指針數組是一些非常重要但又容易混淆的概念。理解它們的特性和應用場景,對于提升嵌入式程序的效率和質量至關重要。一、指針函數與函數指針指針函數:定義:指針
    的頭像 發表于 08-10 08:11 ?1336次閱讀
    面試常考+1:函數指針與指針函數、<b class='flag-5'>數組</b>指針與指針<b class='flag-5'>數組</b>