1. 程式人生 > >Leetcode演算法——53、子陣列的最大和

Leetcode演算法——53、子陣列的最大和

給定一個整數陣列,找到連續子陣列(至少包含一位)的最大和,並返回。

示例:

Input: [-2,1,-3,4,-1,2,1,-5,4],
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

思路

1、分治法

nums 的連續子陣列的最大和,就等於以下三者中的最大值:

  • nums[:mid] 的連續子陣列的最大和
  • nums[mid+1:] 的連續子陣列的最大和
  • 包含nums[mid] 的連續子陣列的最大和

其中,mid 為中位數位置。

時間複雜度的遞推公式:T(n) = 2*T(n/2) + n

可求出:T(n) = O(nlogn)

2、動態規劃法

已知前 k 項的最大子陣列之和,求前 k+1 項的最大子陣列之和,就等於以下兩者的較大值:

  • 前 k 項的最大子陣列之和
  • 包含 nums[k] 的最大子陣列之和

其中第2步,包含 nums[k] 的最大子陣列之和,又可以根據前 k 項中包含 nums[k-1] 的最大子陣列之和來得到,只需要O(1)。

因此整體時間複雜度為 O(n)。

python實現

def maxSubArray(nums):
    """
    :type nums: List[int]
    :rtype: int
    分治法。
    """
# 遞迴結束條件 l = len(nums) if l == 1: return nums[0] # 求取包含nums[mid] 的連續子陣列的最大和 mid = l // 2 max_sum1 = 0 # mid 左半部分的最大和(從末尾向前累加) cur_sum = 0 for num in nums[:mid][::-1]: cur_sum += num max_sum1 = max(max_sum1, cur_sum) max_sum2 = 0 # mid 右半部分的最大和(從起始向後累加)
cur_sum = 0 for num in nums[mid+1:]: cur_sum += num max_sum2 = max(max_sum2, cur_sum) max_sum = nums[mid] + max_sum1 + max_sum2 # 返回三者的最大值 return max(max_sum, maxSubArray(nums[:mid]), maxSubArray(nums[mid+1:])) def maxSubArray2(nums): """ :type nums: List[int] :rtype: int 動態規劃法 """ sub_max = nums[0] # 儲存前i項的最大子陣列之和 last_max = nums[0] # 儲存前i項的且包含最後一位的最大子陣列之和 for i in range(1, len(nums)): last_max = max(last_max + nums[i], nums[i]) sub_max = max(sub_max, last_max) return sub_max if '__main__' == __name__: nums = [-2,1,-3,4,-1,2,1,-5,4] print(maxSubArray2(nums))