1. 题目
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
1.1 示例
-
示例 1 1 1:
-
输入:
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
-
输出: 6 6 6
-
解释: 连续子数组
[4, -1, 2, 1]
的和最大,为 6 6 6 。 -
示例 2 2 2:
-
输入:
nums = [1]
-
输出: 1 1 1
-
示例 3 3 3:
-
输入:
nums = [0]
-
输出: 0 0 0
-
示例 4 4 4:
-
输入:
nums = [-1]
-
输出: − 1 -1 −1
-
示例 5 5 5:
-
输入:
nums = [-100000]
-
输出: − 100000 -100000 −100000
1.2 说明
- 来源: 力扣(LeetCode)
- 链接: https://leetcode-cn.com/problems/maximum-subarray
1.3 提示
- 1 ≤ n u m s . l e n g t h ≤ 3 ∗ 1 0 4 1 \le nums.length \le 3 * 10^4 1≤nums.length≤3∗104
- − 1 0 5 ≤ n u m s [ i ] ≤ 1 0 5 -10^5 \le nums[i] \le 10^5 −105≤nums[i]≤105
1.4 进阶
如果你已经实现复杂度为 O ( n ) O(n) O(n) 的解法,尝试使用更为精妙的分治法求解。
2. 解法一(动态规划)
2.1 分析
解答本题的关键在于正确定义 dp
数组以及找到状态转移方程,这里我们将 dp[i]
定义为以 nums[i]
结尾的子数组中元素和的最大值。
2.2 解答
from typing import List, Union
class Solution:
def max_subarray(self, nums: List[int]) -> Union[int, float]:
dp = [-float('INF')] * len(nums) # dp[i] being the maximum element-wise sum of all sub arrays end with nums[i]
dp[0] = nums[0]
for i in range(1, len(dp)):
dp[i] = max(dp[i - 1] + nums[i], nums[i])
return max(dp)
def main():
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
sln = Solution()
print(sln.max_subarray(nums))
if __name__ == '__main__':
main()
- 执行用时: 32 ms , 在所有 Python3 提交中击败了 93.03% 的用户;
- 内存消耗: 15.2 MB , 在所有 Python3 提交中击败了 84.08% 的用户。
2.3 复杂度
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 为
nums
数组的长度。我们只需要遍历一遍数组即可求得答案。- 空间复杂度: O ( n ) O(n) O(n)。我们需要使用
dp
作为辅助存储容器。
实际上,上述解法还可以进一步优化以进一步提高算法的空间复杂度:
from typing import List, Union
class Solution:
def efficient_max_subarray(self, nums: List[int]) -> int:
max_sum = nums[0]
cur_sum = nums[0]
for i in range(1, len(nums)):
cur_sum = max(cur_sum + nums[i], nums[i])
if cur_sum > max_sum:
max_sum = cur_sum
return max_sum
def main():
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
sln = Solution()
print(sln.efficient_max_subarray(nums))
if __name__ == '__main__':
main()
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n 为
nums
数组的长度。我们只需要遍历一遍数组即可求得答案。- 空间复杂度: O ( 1 ) O(1) O(1)。我们只需要常数空间存放若干变量。