LeetCode 第 53 題:連續(xù)子數(shù)組的最大和

標(biāo)簽(空格分隔): 動(dòng)態(tài)規(guī)劃 分治法

傳送門:53. 最大子序和富岳。

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

示例:

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

進(jìn)階:

如果你已經(jīng)實(shí)現(xiàn)復(fù)雜度為 O(n) 的解法狼电,嘗試使用更為精妙的分治法求解。

分析:


總結(jié):分類討論的標(biāo)準(zhǔn)是:若之前的和小于 0肩碟,則將最大和置為當(dāng)前值,否則計(jì)算最大和削祈。

思路1:動(dòng)態(tài)規(guī)劃

下面展示了標(biāo)準(zhǔn)的動(dòng)態(tài)規(guī)劃的寫法脑漫。

Java 代碼:

public class Solution {
    
    public int FindGreatestSumOfSubArray(int[] array) {
        int n = array.length;
        if (n == 0) {
            return 0;
        }
        int[] dp = new int[n];
        dp[0] = array[0];
        int res = array[0];
        for (int i = 1; i < n; i++) {
            dp[i] = Integer.max(dp[i - 1] + array[i], array[i]);
            res = Integer.max(res, dp[i]);
        }
        return res;
    }

    public static void main(String[] args) {
        int[] nums = new int[]{6, -3, -2, 7, -15, 1, 2, 2};
        Solution solution = new Solution();
        int findGreatestSumOfSubArray = solution.FindGreatestSumOfSubArray(nums);
        System.out.println(findGreatestSumOfSubArray);
    }
}

這道題主要就在狀態(tài)的定義上要思考一下,這里題目中的關(guān)鍵字是“連續(xù)”优幸,所以如果我們定義的狀態(tài)就是題目要求的結(jié)果:dp[i] 表示 nums 在區(qū)間 [0,i] 中連續(xù)子數(shù)組的最大和,那么在思考狀態(tài)轉(zhuǎn)移方程的時(shí)候网杆,dp[i] 之前的,例如 dp[i-1] 就有可能是是更前面的連續(xù)子數(shù)組的最大和碳却,不利于我們分類討論。

因此笑旺,我們可以定義狀態(tài):dp[i] 表示以 nums[i] 結(jié)尾的連續(xù)子數(shù)組的最大和。

這樣定義狀態(tài)筒主,分類討論就變得容易多了,因?yàn)?dp[i-1] 表示一定以 nums[i-1] 結(jié)尾乌妙,那么 dp[i] 就可以有兩種情況:

1、把 nums[i] 直接接在 dp[i-1] 表示的那個(gè)數(shù)組的后面藤韵;

例如火诸,dp[i-1] = 3,nums[i] = 5奈搜,當(dāng)然接在后面悉盆,越接越大馋吗。

2、單獨(dú)的一個(gè) nums[i] 宏粤。

這種情況也比較好想到,比如:dp[i-1] = -3绍哎,nums[i] = 5,加上前面的數(shù)反而我越來越小了崇堰,干脆我另起爐灶吧沃于。

以上兩種情況的最大值就是 dp[i] 的值。

最后不要忘記了繁莹,最終的結(jié)果應(yīng)該是把所有的 dp[0],dp[1]咨演,……,dp[n-1] 都看一遍薄风,求最大值饵较。

重點(diǎn):動(dòng)態(tài)規(guī)劃問題。狀態(tài)是:以當(dāng)前數(shù)字為結(jié)尾的連續(xù)子數(shù)組的最大和村刨。

Python 代碼:

class Solution(object):
    def maxSubArray(self, nums):
        """
            :type nums: List[int]
            :rtype: int
            """

        l = len(nums)
        if l == 0:
            return 0
        if l == 1:
            return nums[0]
        dp = [0 for _ in range(l)]
        dp[0] = nums[0]

        for i in range(1, l):
            dp[i] = max(dp[i - 1] + nums[i], nums[i])
            # 最后不要忘記拉通求一遍最大值,或者在上面遍歷的時(shí)候嵌牺,就保存最大值
            return max(dp)

或者你可以在遍歷的時(shí)候,就把最大值求出來逆粹。

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l = len(nums)
        if l == 0:
            return 0
        # 以索引 i 結(jié)尾的最大子數(shù)組的和
        end_i_max = nums[0]
        # 最后返回的數(shù)
        res = nums[0]
        for i in range(1, l):
            # 例:[-3,1]
            end_i_max = max(nums[i], end_i_max + nums[i])
            res = max(res, end_i_max)
        return res

思路2:分治法

參考資料:連續(xù)子數(shù)組最大和

Python 寫法:

class Solution(object):
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n == 0:
            return 0
        return self.__max_sub_array(nums, 0, n - 1)

    def __max_sub_array(self, nums, left, right):
        if left == right:
            return nums[left]
        mid = left + (right - left) // 2
        return max(self.__max_sub_array(nums, left, mid),
                   self.__max_sub_array(nums, mid + 1, right),
                   self.__max_cross_array(nums, left, mid, right))

    def __max_cross_array(self, nums, left, mid, right):
        """
        一定包含 nums[mid] 元素的最大連續(xù)子數(shù)組的和
        思路是看看左邊擴(kuò)散到底,得到一個(gè)最大數(shù)
        右邊擴(kuò)散到底得到一個(gè)最大數(shù)
        :param nums:
        :param mid:
        :param right:
        :return:
        """
        ls = 0
        j = mid - 1
        s1 = 0
        while j >= left:
            s1 += nums[j]
            ls = max(ls, s1)
            j -= 1

        rs = 0
        j = mid + 1
        s2 = 0
        while j <= right:
            s2 += nums[j]
            rs = max(rs, s2)
            j += 1

        return ls + nums[mid] + rs


if __name__ == '__main__':
    s = Solution()
    nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
    result = s.maxSubArray(nums)
    print(result)

(本節(jié)完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阿浓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子芭毙,更是在濱河造成了極大的恐慌,老刑警劉巖退敦,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侈百,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)翰铡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锭魔,“玉大人,你說我怎么就攤上這事迷捧〖鹪祝” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵巡社,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我手趣,道長(zhǎng),這世上最難降的妖魔是什么绿渣? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮中符,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淀散。我一直安慰自己右莱,他們只是感情好档插,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著郭膛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪则剃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天棍现,我揣著相機(jī)與錄音,去河邊找鬼轴咱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朴肺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坚洽,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼讶舰!你這毒婦竟也來了需了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤肋乍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后墓造,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锚烦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涮俄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡彻亲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出睹栖,到底是詐尸還是另有隱情,我是刑警寧澤野来,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布恼除,位于F島的核電站曼氛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏舀患。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一聊浅、第九天 我趴在偏房一處隱蔽的房頂上張望餐抢。 院中可真熱鬧低匙,春花似錦、人聲如沸顽冶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绞呈。三九已至,卻和暖如春佃声,著一層夾襖步出監(jiān)牢的瞬間艺智,已是汗流浹背秉溉。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留召嘶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓弄跌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親铛只。 傳聞我的和親對(duì)象是個(gè)殘疾皇子埠胖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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