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

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

3天內不再提示

最大子序和,貪心解法

算法與數據結構 ? 來源:代碼隨想錄 ? 作者:代碼隨想錄 ? 2022-05-10 10:37 ? 次閱讀

53. 最大子序和

力扣題目鏈接:https://leetcode-cn.com/problems/maximum-subarray

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

示例: 輸入: [-2,1,-3,4,-1,2,1,-5,4] 輸出: 6 解釋:連續(xù)子數組[4,-1,2,1] 的和最大,為 6。

暴力解法

暴力解法的思路,第一層for 就是設置起始位置,第二層for循環(huán)遍歷數組尋找最大值

時間復雜度:O(n^2) 空間復雜度:O(1)

classSolution{
public:
intmaxSubArray(vector<int>&nums){
intresult=INT32_MIN;
intcount=0;
for(inti=0;i//設置起始位置
count=0;
for(intj=i;j//每次從起始位置i開始遍歷尋找最大值
count+=nums[j];
result=count>result?count:result;
}
}
returnresult;
}
};

以上暴力的解法C++勉強可以過,其他語言就不確定了。

貪心解法

貪心貪的是哪里呢?

如果 -2 1 在一起,計算起點的時候,一定是從1開始計算,因為負數只會拉低總和,這就是貪心貪的地方!

局部最優(yōu):當前“連續(xù)和”為負數的時候立刻放棄,從下一個元素重新計算“連續(xù)和”,因為負數加上下一個元素 “連續(xù)和”只會越來越小。

全局最優(yōu):選取最大“連續(xù)和”

局部最優(yōu)的情況下,并記錄最大的“連續(xù)和”,可以推出全局最優(yōu)。

從代碼角度上來講:遍歷nums,從頭開始用count累積,如果count一旦加上nums[i]變?yōu)樨摂?,那么就應該從nums[i+1]開始從0累積count了,因為已經變?yōu)樨摂档腸ount,只會拖累總和。

這相當于是暴力解法中的不斷調整最大子序和區(qū)間的起始位置。

那有同學問了,區(qū)間終止位置不用調整么?如何才能得到最大“連續(xù)和”呢?

區(qū)間的終止位置,其實就是如果count取到最大值了,及時記錄下來了。例如如下代碼:

if(count>result)result=count;

這樣相當于是用result記錄最大子序和區(qū)間和(變相的算是調整了終止位置)。

如動畫所示:

88d26216-d009-11ec-bce3-dac502259ad0.gif53.最大子序和

紅色的起始位置就是貪心每次取count為正數的時候,開始一個區(qū)間的統(tǒng)計。

那么不難寫出如下C++代碼(關鍵地方已經注釋)

classSolution{
public:
intmaxSubArray(vector<int>&nums){
intresult=INT32_MIN;
intcount=0;
for(inti=0;iif(count>result){//取區(qū)間累計的最大值(相當于不斷確定最大子序終止位置)
result=count;
}
if(count<=?0)count=0;//相當于重置最大子序起始位置,因為遇到負數一定是拉低總和
}
returnresult;
}
};

時間復雜度:O(n) 空間復雜度:O(1)

當然題目沒有說如果數組為空,應該返回什么,所以數組為空的話返回啥都可以了。

不少同學認為 如果輸入用例都是-1,或者 都是負數,這個貪心算法跑出來的結果是0, 這是又一次證明腦洞模擬不靠譜的經典案例,建議大家把代碼運行一下試一試,就知道了,也會理解 為什么 result 要初始化為最小負數了。

動態(tài)規(guī)劃

當然本題還可以用動態(tài)規(guī)劃來做,當前「代碼隨想錄」主要講解貪心系列,后續(xù)到動態(tài)規(guī)劃系列的時候會詳細講解本題的dp方法。

那么先給出我的dp代碼如下,有時間的錄友可以提前做一做:

classSolution{
public:
intmaxSubArray(vector<int>&nums){
if(nums.size()==0)return0;
vector<int>dp(nums.size(),0);//dp[i]表示包括i之前的最大連續(xù)子序列和
dp[0]=nums[0];
intresult=dp[0];
for(inti=1;i1]+nums[i],nums[i]);//狀態(tài)轉移公式
if(dp[i]>result)result=dp[i];//result保存dp[i]的最大值
}
returnresult;
}
};

時間復雜度:O(n) 空間復雜度:O(n)

總結

本題的貪心思路其實并不好想,這也進一步驗證了,別看貪心理論很直白,有時候看似是常識,但貪心的題目一點都不簡單!

后續(xù)將介紹的貪心題目都挺難的,哈哈,所以貪心很有意思,別小看貪心!

其他語言版本

Java

classSolution{
publicintmaxSubArray(int[]nums){
if(nums.length==1){
returnnums[0];
}
intsum=Integer.MIN_VALUE;
intcount=0;
for(inti=0;i//取區(qū)間累計的最大值(相當于不斷確定最大子序終止位置)
if(count<=?0){
count=0;//相當于重置最大子序起始位置,因為遇到負數一定是拉低總和
}
}
returnsum;
}
}
//DP方法
classSolution{
publicintmaxSubArray(int[]nums){
intans=Integer.MIN_VALUE;
int[]dp=newint[nums.length];
dp[0]=nums[0];
ans=dp[0];

for(inti=1;i1]+nums[i],nums[i]);
ans=Math.max(dp[i],ans);
}

returnans;
}
}

Python

classSolution:
defmaxSubArray(self,nums:List[int])->int:
result=-float('inf')
count=0
foriinrange(len(nums)):
count+=nums[i]
ifcount>result:
result=count
ifcount<=?0:
count=0
returnresult

Go

funcmaxSubArray(nums[]int)int{
maxSum:=nums[0]
fori:=1;ilen(nums);i++{
ifnums[i]+nums[i-1]>nums[i]{
nums[i]+=nums[i-1]
}
ifnums[i]>maxSum{
maxSum=nums[i]
}
}
returnmaxSum
}

--- EOF ---

審核編輯 :李倩


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

    關注

    1

    文章

    181

    瀏覽量

    39551
  • 數組
    +關注

    關注

    1

    文章

    411

    瀏覽量

    25824

原文標題:最大子序和,又貪心又DP

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

收藏 人收藏

    評論

    相關推薦

    ?核對電纜相的小技巧

    核對電纜相的技巧要訣核對相很重要,相不對事故到;一般沒有相表,蓄電池燈用靠技巧;一側相已明了,把它接地電阻小,一根燈線向地跑,還有
    的頭像 發(fā)表于 08-08 16:08 ?192次閱讀
    ?核對電纜相<b class='flag-5'>序</b>的小技巧

    保護器報警怎么解決

    保護器是一種用于檢測和保護電動機相錯誤的裝置,當電動機的相錯誤時,相保護器會發(fā)出報警信號,以避免電動機因相錯誤而損壞或發(fā)生故障。
    的頭像 發(fā)表于 08-02 14:20 ?1211次閱讀

    保護器如何知道正確相

    保護器是一種用于保護電氣設備免受相錯誤影響的裝置。在電力系統(tǒng)中,相是指三相交流電的相位關系。正確的相可以確保電氣設備正常運行,而錯誤的相
    的頭像 發(fā)表于 08-02 14:13 ?398次閱讀

    保護器怎么判斷好壞

    保護器是一種用于檢測和保護電力系統(tǒng)中相錯誤的裝置。在電力系統(tǒng)中,相錯誤可能會導致設備損壞、供電中斷等問題,因此相保護器在電力系統(tǒng)中具有重要的作用。 一、相
    的頭像 發(fā)表于 08-02 14:11 ?561次閱讀

    互感器型號及參數詳解

    互感器是一種用于測量和保護電力系統(tǒng)中零電流的設備。在電力系統(tǒng)中,零電流是指三相電流不平衡時產生的電流,它可能導致設備損壞和電力系統(tǒng)的不穩(wěn)定。因此,零互感器在電力系統(tǒng)中具有重要
    的頭像 發(fā)表于 07-25 15:59 ?536次閱讀

    、負和零的產生原因

    、負和零是電力系統(tǒng)中常用的三個概念,它們分別表示三相交流電的相關系。在電力系統(tǒng)中,三相交流電的相關系對于電力系統(tǒng)的穩(wěn)定運行和設備
    的頭像 發(fā)表于 07-15 10:51 ?1983次閱讀

    分量各有什么特點

    、負和零分量是電力系統(tǒng)中分析不對稱故障的重要概念。它們分別代表了三相交流系統(tǒng)中的三種不同電流分布狀態(tài)。 正分量 正分量是指三相電
    的頭像 發(fā)表于 07-15 10:49 ?748次閱讀

    繼電器簡介 相繼電器的應用原理

    在許多三相交流電應用的場合,相的正確有時是一項必須的條件,錯誤的相或缺相有可能導致設備工作不正常甚至損壞。
    的頭像 發(fā)表于 02-23 16:07 ?1.2w次閱讀
    相<b class='flag-5'>序</b>繼電器簡介 相<b class='flag-5'>序</b>繼電器的應用原理

    為什么輸電線路的正阻抗比零阻抗小呢?

    為什么輸電線路的正阻抗比零阻抗小呢? 輸電線路的正阻抗比零阻抗小是由于以下幾個原因: 首先,輸電線路的正阻抗在設計和施工過程中通常
    的頭像 發(fā)表于 02-18 11:41 ?1901次閱讀

    單相接地時正電流與負電流、零電流相等嗎?

    單相接地時正電流與負電流、零電流相等嗎? 在單相接地系統(tǒng)中,正電流、負電流和零電流是
    的頭像 發(fā)表于 02-04 09:56 ?2507次閱讀

    什么是正電流?什么是負電流?什么是零電流?

    什么是正電流?什么是負電流?什么是零電流? 正電流:正電流是指在三相對稱電壓系統(tǒng)中,三相電流的相位角相同,大小相等,且按照a-b-
    的頭像 發(fā)表于 02-04 09:43 ?1.1w次閱讀

    保護的優(yōu)點有哪些?

    保護是一種利用零電流、零電壓和零功率來構成保護接地短路的繼電保護裝置。
    的頭像 發(fā)表于 12-13 11:45 ?1299次閱讀

    含受控源電路變換控制量解法初探

    電子發(fā)燒友網站提供《含受控源電路變換控制量解法初探.pdf》資料免費下載
    發(fā)表于 11-18 15:11 ?0次下載
    含受控源電路變換控制量<b class='flag-5'>解法</b>初探

    表使用注意事項

    一、相的概念 三相交流電勢瞬時值到達正最大值有一定的先后次序,這種先后次序叫作相。如eA先到達正最大值,隨后是 eB,最后是eC,此時的相
    的頭像 發(fā)表于 09-26 10:50 ?1355次閱讀

    三相電路的正、負和零分量

    一、在三相電路中,由于負載的不平衡,往往會使電路中的電壓、電流不對稱。要對這種不對稱電壓或電流進行分析,可以把它們分解成三組分量:正分量、負分量、零分量。設電源的相為ABC,則
    的頭像 發(fā)表于 09-24 16:14 ?9398次閱讀