leetcode-最大子序和

題目:

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


背景:

????????本題為非常經(jīng)典的一道算法入門(mén)題,有著多種非常高效的解題方法,可以幫助答題感受到“找到問(wèn)題的關(guān)鍵與解決問(wèn)題的核心最小點(diǎn)”這個(gè)思維的關(guān)鍵与帆。

????????原本覺(jué)得此題很簡(jiǎn)單纺且,也很容易給同事們講清楚。實(shí)際在講的時(shí)候發(fā)現(xiàn)自己也并沒(méi)有把所有的方法的根本原理徹底想清楚整陌,所以在此做一個(gè)完整的整理與分析锁荔,供自己以后回憶、以及讓大家更好的理解黎做。

? ? ? ? 在此給大家分享五種解法叉跛,歡迎一起討論以及使用其它方法實(shí)現(xiàn)。


一蒸殿、無(wú)暴力筷厘,不解題

? ? ? ? 作為個(gè)人習(xí)慣,遇到一個(gè)問(wèn)題總是喜歡先考慮能否用暴力方法解決問(wèn)題宏所。因?yàn)楸┝Ψ椒ǖ乃季S方式最為簡(jiǎn)單酥艳,并不需要過(guò)多的考慮問(wèn)題背后所蘊(yùn)含的原理與思路。而且在實(shí)際生活中爬骤,可能很多問(wèn)題我們使用暴力方式就足夠了玖雁,這樣會(huì)給開(kāi)發(fā)以及運(yùn)維人員都大大減少工作量盖腕。

方法一赫冬,暴力到底:

? ? ? ? 題目要求是找出最大子序和,那么我們就把所有的子序都找出來(lái)溃列,并且求出每個(gè)子序的和然后找到最大的一個(gè)就可以了劲厌。題目已給一個(gè)序列,我們需要做的就是確定所有能找到的開(kāi)始序號(hào)與結(jié)束序號(hào)听隐,然后把這個(gè)序號(hào)中的所有子序和都求出來(lái)补鼻。具體實(shí)現(xiàn)如下:

????????此方法中我們用了三層循環(huán),即在確定了某一個(gè)子序的開(kāi)始序號(hào)(i)與結(jié)束序號(hào)(j)的位置后雅任,枚舉i與j中間的每個(gè)點(diǎn)k风范,計(jì)算從i到k的子序和,時(shí)間復(fù)雜度是n^3沪么,n為序列的長(zhǎng)度硼婿。

方法2,暴力也可以?xún)?yōu)化一點(diǎn):

? ? ? ? 在方法一中禽车,對(duì)于i與j中間的每一個(gè)點(diǎn)k寇漫,我們都會(huì)計(jì)算一遍從i到k的所有數(shù)之和,其實(shí)這里我們做了很多次無(wú)用的計(jì)算殉摔,即點(diǎn)i到點(diǎn)k的數(shù)之和州胳,為點(diǎn)i到點(diǎn)k-1的數(shù)之和,加上點(diǎn)k的數(shù)值逸月。同時(shí)栓撞,我們每一個(gè)起點(diǎn)i開(kāi)始的子序列,最長(zhǎng)的結(jié)尾j都一定是在完整序列的最后碗硬,所以這里我們只需要兩層循環(huán)就可以了:

方法3瓤湘,直接暴力但是可靠的線性算法:

????????在講這個(gè)算法前捌归,首先我們需要弄清楚的是最大子序和的這個(gè)子序所包含的一些特性:

*1).最大子序的開(kāi)始和結(jié)尾兩個(gè)數(shù)一定都是正數(shù),如果不是岭粤,那么子序列拋棄這個(gè)負(fù)數(shù)惜索,會(huì)變的更大。

*2).最大子序列中任何一個(gè)包含了第一個(gè)數(shù)的左子序列或者包含了最后一個(gè)數(shù)的右子序列剃浇,其和一定是正數(shù)巾兆,如果不是,那么最大子序列拋棄這一段子序虎囚,會(huì)變得更大角塑。

*3).最大子序列外左邊第一個(gè)數(shù)開(kāi)始往左任意連續(xù)多個(gè)數(shù)之和以及最大子序列外右邊第一個(gè)數(shù)開(kāi)始任意多個(gè)數(shù)之和,一定都是小于零的淘讥,否則最大子序列可以加上這一段數(shù)變得更大圃伶。

????????由以上三個(gè)特性,我們可以實(shí)現(xiàn)這樣一個(gè)方法:

? ? ? ? 我們從序列的第一個(gè)數(shù)開(kāi)始往后掃描蒲列。如果這個(gè)數(shù)小于零窒朋,那么它一定不會(huì)是最大子序列的第一個(gè)數(shù),我們就繼續(xù)往后掃描(特性*1)蝗岖。如果這個(gè)數(shù)大于零侥猩,我們認(rèn)為它可能是最大子序列的第一個(gè)數(shù),我們從這個(gè)數(shù)開(kāi)始求和抵赢,每往后掃到一個(gè)數(shù)欺劳,就把新的數(shù)加到這個(gè)和,只要這個(gè)和還大于零铅鲤,這連續(xù)的子序列就可能是最大子序列的一部分(特性*2)划提。在不斷加數(shù)的過(guò)程中,我們維護(hù)一個(gè)全局的變量邢享,用來(lái)記錄最大子序和鹏往,每次掃描一個(gè)數(shù),都判斷這個(gè)變量能否更新驼仪。一旦我們?cè)诩拥倪^(guò)程中掸犬,子序和小于零了,那么這之前的所有數(shù)我們都直接拋棄绪爸,因?yàn)橹暗臄?shù)不會(huì)是最大子序列的一部分(特性*3),我們從下一個(gè)數(shù)開(kāi)始計(jì)算新的子序列宙攻。

? ? ? ? 如此操作奠货,是需要我們對(duì)整個(gè)序列從左到右掃描一次,我們就可以在這個(gè)過(guò)程中得到最大子序和座掘。實(shí)現(xiàn)如下:

時(shí)間復(fù)雜度O(n)

方法4递惋,狀態(tài)轉(zhuǎn)移柔滔,動(dòng)態(tài)規(guī)劃:

? ? ? ? 方法3中,可以認(rèn)為我們每次都是確定了一個(gè)子序列的第一個(gè)數(shù)萍虽,然后從該數(shù)開(kāi)始計(jì)算之后的子序列睛廊,其實(shí)我們也可以根據(jù)子序列的最后一個(gè)數(shù)來(lái)判斷子序列的和的大小。

? ? ? ? 最大子序列一定是以某一個(gè)序列中的數(shù)為結(jié)尾杉编,這個(gè)數(shù)一定是正數(shù)超全。對(duì)序列中的每個(gè)數(shù),都有兩種可能:

(1)這個(gè)數(shù)與之前若干數(shù)組成序列邓馒,這個(gè)數(shù)是最后一個(gè)嘶朱。

(2)這個(gè)數(shù)就是單獨(dú)的一個(gè)序列。

? ? ? ? 我們認(rèn)為光酣,在任意一個(gè)位置i疏遏,如果確認(rèn)了i位置上的數(shù)是序列的最后一個(gè)數(shù),那么這個(gè)序列的和最大應(yīng)該是以i-1為結(jié)尾的序列加上i位置的數(shù)救军,和單獨(dú)只有i這個(gè)位置上的數(shù)财异,兩者中較大的一個(gè)。如果以f[i]記錄以第i個(gè)位置的數(shù)為結(jié)尾的最大子序之和唱遭,具體狀態(tài)轉(zhuǎn)移如下:

????????f[i] = max( f[i-1] + nums[i],? nums[i])

????????如此我們掃描一遍整個(gè)數(shù)組宝当,從第一個(gè)位置到最后一個(gè)位置,每次都已當(dāng)前位置為子序列最后一個(gè)數(shù)胆萧,求得當(dāng)前位置結(jié)束的最大子序列庆揩,同時(shí)更新全局的最大子序和,便能得到最終的最大子序和跌穗。具體實(shí)現(xiàn)如下:

時(shí)間復(fù)雜度O(n)

方法5订晌,最優(yōu)美的分治算法:

? ? ? ? 最大子序列只可能有三種情況:在序列的左半部分,在序列的右半部分蚌吸,橫跨序列中間(包含左半部分最后一個(gè)與右半部分第一個(gè))锈拨。所以我們需要做的就是,對(duì)比著三部分的大小羹唠,然后返回最大的一個(gè)和奕枢。

? ? ? ? 對(duì)于中間部分,求和的辦法是從中間分別求出往左的最大值與往右的最大值佩微,兩邊加起來(lái)即為最大的橫跨兩邊的子序列缝彬。

時(shí)間復(fù)雜度nlogn


? ? ? ? 解題絕對(duì)不是把題做出來(lái)、能得到一個(gè)答案就可以哺眯。嘗試不同方法的過(guò)程谷浅,其實(shí)是一個(gè)探索問(wèn)題的根本問(wèn)題的過(guò)程。找到了最根本的核心點(diǎn),也就能相應(yīng)的得到正確的解法一疯。

? ? ? ? 使用更快的算法來(lái)解題撼玄,不僅僅是為了炫技,更是為了能解決更艱難情況下的問(wèn)題墩邀,讓所有問(wèn)題都變成可解的掌猛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市眉睹,隨后出現(xiàn)的幾起案子荔茬,更是在濱河造成了極大的恐慌,老刑警劉巖辣往,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兔院,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡站削,警方通過(guò)查閱死者的電腦和手機(jī)坊萝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)许起,“玉大人十偶,你說(shuō)我怎么就攤上這事≡跋福” “怎么了惦积?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵金度,是天一觀的道長(zhǎng)谐丢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)丘薛,這世上最難降的妖魔是什么鹿寻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任睦柴,我火速辦了婚禮,結(jié)果婚禮上毡熏,老公的妹妹穿的比我還像新娘坦敌。我一直安慰自己,他們只是感情好痢法,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布狱窘。 她就那樣靜靜地躺著,像睡著了一般财搁。 火紅的嫁衣襯著肌膚如雪蘸炸。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天妇拯,我揣著相機(jī)與錄音幻馁,去河邊找鬼洗鸵。 笑死越锈,一個(gè)胖子當(dāng)著我的面吹牛仗嗦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甘凭,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼稀拐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了丹弱?” 一聲冷哼從身側(cè)響起德撬,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎躲胳,沒(méi)想到半個(gè)月后蜓洪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坯苹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年隆檀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粹湃。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恐仑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出为鳄,到底是詐尸還是另有隱情裳仆,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布孤钦,位于F島的核電站歧斟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏偏形。R本人自食惡果不足惜静袖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壳猜。 院中可真熱鬧勾徽,春花似錦、人聲如沸统扳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)咒钟。三九已至吹由,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間朱嘴,已是汗流浹背倾鲫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工粗合, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人乌昔。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓隙疚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親磕道。 傳聞我的和親對(duì)象是個(gè)殘疾皇子供屉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 題目 解析 參考leetcode-最大子序和(四種) 第一種解法——暴力枚舉法 O(N^3) 從左往右依次找出所有...
    雇個(gè)城管打天下閱讀 411評(píng)論 0 0
  • 給定一個(gè)整數(shù)數(shù)組 nums ,找到一個(gè)具有最大和的連續(xù)子數(shù)組(子數(shù)組最少包含一個(gè)元素)溺蕉,返回其最大和伶丐。 示例: 輸...
    小白學(xué)編程閱讀 169評(píng)論 0 0
  • 2018年6月2日 六一就在孩子們的快樂(lè),爸爸媽媽們的疲倦中度過(guò) 我們的選址疯特,惠州十里銀灘哗魂; 我們的休息地 (以實(shí)...
    晴致生活館閱讀 241評(píng)論 0 0
  • UI架構(gòu)小史3(MVC/MVP/MVVM)
    gadfly_only閱讀 647評(píng)論 0 51
  • 1、內(nèi)存管理 - 棧 or 堆 無(wú)論是java還是C漓雅,內(nèi)存分配录别,本質(zhì)上就是 棧和堆兩個(gè)類(lèi)型。簡(jiǎn)單來(lái)說(shuō)故硅,代碼邏輯處理...
    軒居晨風(fēng)閱讀 473評(píng)論 0 1