題目描述:
輸入乙個整型陣列,陣列裡有正數也有負數。陣列中的乙個或連續多個整數組成乙個子陣列。求所有子陣列的和的最大值。
要求時間複雜度為o(n)。
示例1:
輸入: nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
注意:本題與主站 53 題相同:
個人思路:
這道題描述了乙個最優化問題,因此可以考慮是否滿足動態規劃(dynamic programming,dp)的解題要求。
一般可以應用動態規劃求解的問題具有以下幾個特點(總結自《劍指offer》):
該問題是求解乙個最優化的問題,例如最大值、最小值等。
該問題的最優解依賴於一些子問題的最優解,這些子問題由整體問題分解而來。(這裡的依賴關係以狀態轉移方程來描述)
這些子問題之間還存在相互重疊的更小的子問題。(dp演算法正是利用了子問題的重疊性,重複利用之前計算的結果,從而降低計算量,提高程式的執行效率)
從上往下分析問題,從下往上求解問題。
對比以上特點,可以發現本題可以使用動態規劃進行求解。下面需要完成dp的三個重要設定——狀態定義、初始化以及狀態轉移。
狀態定義:其實也就是需要設定我們想要求解的子問題,或者說我們想要記錄的一些資料。狀態定義可以有很多種,很多題目多種狀態定義都可以得到正確的結果,狀態定義無非是為了後續方便寫出狀態轉移方程,一般而言題目待求解的問題即可作為狀態定義,但也有例外,例如本題。本題要求我們求解乙個陣列中的所有子陣列的最大和。(這裡我們需要區分子陣列與子串行的區別:子陣列要求各個數相鄰,可以看做是原陣列的乙個切片;而子串行不要求各個數相鄰,只需要保證各個數的相對位置不變即可,可以看做是原陣列一系列切片的組合。)假設我們定義狀態為:dp[i] 代表陣列nums[:i+1]中子陣列的和的最大值,此時最終我們只需輸出dp[-1]即為原問題的結果。但是這種狀態定義使得我們很難去描述狀態轉移方程,因為問題要求求解的是子陣列,我們難以直接判斷nums[i]是否是最優解dp[i]的乙個貢獻者,此時對於nums[i+1]難以直接與dp[i]進行關聯。因此,我們不妨設定狀態為:dp[i]表示以nums[i]結尾的陣列中子陣列的和的最大值,從而方便我們定義狀態轉移。
初始化:dp問題中合理的初始化有利於統一邊界判斷,減少**量以及出錯的情況。本題最基礎的情況就是乙個數的陣列,因此可以相應進行初始化,具體可見後續**。
狀態轉移:牢記我們的狀態定義(dp[i]表示以nums[i]結尾的陣列中子陣列的和的最大值),就不難寫出狀態轉移方程了:dp[i+1] = max(nums[i+1], dp[i] + nums[i+1])
再完成以上設定後,即可編寫**了。我覺得dp問題中,最重要的就是狀態定義,一旦狀態定義完成了,一切(初始化以及狀態轉移)都可以圍繞其構建完成,一般狀態定義就可以定義為原問題的簡單子問題即可。
具體**如下:
class solution:
def maxsubarray(self, nums: list[int]) -> int:
if not nums:
return -1
# dp表示以當前元素結尾的子陣列的最大和
dp = [nums[0]] * len(nums) # 狀態定義以及初始化
# dp[i] = max(nums[i], dp[i - 1] + nums[i]) 狀態轉移方程
for i in range(1, len(nums)):
dp[i] = max(nums[i], dp[i - 1] + nums[i])
return max(dp) # 根據狀態定義求解最終原問題的結果
面試題42 連續子陣列的最大和
題目描述 hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個...
面試題42 連續子陣列的最大和
輸入乙個整型陣列,陣列裡有正數也有負數。陣列中的乙個或連續多個整數組成乙個子陣列。求所有子陣列的和的最大值。要求時間複雜度為o n 示例1 輸入 nums 2,1,3,4,1,2,1,5,4 輸出 6 解釋 連續子陣列 4,1,2,1 的和最大,為 6。1 arr.length 10 5 100 a...
面試題42 連續子陣列的最大和
面試題42 hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0...