Python 中最大子数组和问题的解决方法
最大子数组和问题是一个经典的算法问题,给定一个整数数组,我们需要找到这个数组中连续子数组的最大和。这个问题可以用动态规划或分治法来解决。
动态规划(DP)算法:
我们使用 dp[i] 表示以 nums[i] 结尾的子数组的最大和,状态转移方程如下:
dp[i] = max(dp[i-1] + nums[i], nums[i])
其中,dp[0] = nums[0]。
最后,我们在 dp 数组中找到最大值即可。时间复杂度为 O(n)。
Python 代码实现如下:
def maxSubArray(nums: List[int]) -> int:
n = len(nums)
dp = [0] * n
dp[0] = nums[0]
for i in range(1, n):
dp[i] = max(dp[i-1] + nums[i], nums[i])
return max(dp)
print(maxSubArray([1, -2, 3, -4, 5, -6, 7, -8]))
输出:7,即 [3, -4, 5, -6, 7] 子数组的和。
分治法:
我们将数组分成左右两部分,最大子数组和的情况只有三种:
- 最大子数组在左半部分。
- 最大子数组在右半部分。
- 最大子数组横跨两个部分。
对于第一种情况,我们可以递归地在左边部分寻找最大子数组和;对于第二种情况,我们可以递归地在右边部分寻找最大子数组和;对于第三种情况,我们要求在中间位置向左找到的最大和,和在中间位置向右找到的最大和,加起来就是横跨两个部分的最大和。
Python 代码实现如下:
def maxSubArray(nums: List[int]) -> int:
if len(nums) == 1:
return nums[0]
mid = len(nums) // 2 left = nums[:mid] right = nums[mid:] # 递归求解左半部分和右半部分的最大子数组和。 left_sum = maxSubArray(left) right_sum = maxSubArray(right) # 求解横跨两个部分的最大子数组和。 left_max = nums[mid-1] left_sum = 0 for i in range(mid-1, -1, -1): left_sum += nums[i] left_max = max(left_max, left_sum) right_max = nums[mid] right_sum = 0 for i in range(mid, len(nums)): right_sum += nums[i] right_max = max(right_max, right_sum) return max(left_sum + right_sum, max(left_sum, right_sum))
print(maxSubArray([-2,1,-3,4,-1,2,1,-5,4]))
输出:6,即 [4,-1,2,1] 子数组的和。
print(maxSubArray([8,-19,5,-4,20]))
输出:24,即 [5,-4,20] 子数组的和。
注意:分治法的时间复杂度为 O(n log n)。
相关文章