LeetCode 热题 100 之 53. 最大子数组和

发布时间 2023-07-25 16:59:19作者: anamazingclown

题目

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]
输出:1

示例 3:

输入:nums = [5,4,-1,7,8]
输出:23

提示:

1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4

思路

暴力解法:超时

先计算前缀和再两层循环找到最大值

动态规划:

题目要求我们找出连续子数组的最大和,并没有要求得。到是最大的是哪一个,因此通常可以用动态规划解决。
动态规划的思想通过解决了一个一个简单的问题,进而把简单的问题的解组成了复杂的问题的解。
对问题进行分解,要找到连续子数组的最大和,那么对给定的每个位置上的数字进行分析,比如计算[-2,1,-3,4,-1,2,1,-5,4]的最大子数组和,分解成9个子问题,1:以-2为结尾的子数组其和最大值为多少?2:以1为结尾的最大子数组和为多少,3:以-3为结果的最大子数组和为多少?……
子问题1:以-2结尾的子数组为[-2],因此的答案是-2。z(自身nums[0])
子问题2:以1结尾的子数组为[-2,1],[1]可以发现的答案是1。(自身 nums[1])
子问题3,以-3即为的子数组为[-2,1,-3],[1,-3],[-3],可以发现其答案是-2(前一个问题的答案+ nums[2])
……
定义子问题
dp[i]:表示以 nums[i] 结尾的连续子数组的最大和。由dp[i]定义可知nums[i]一定会选取。
假设数组 nums 的值全都严格大于 0,那么一定有 dp[i] = dp[i - 1] + nums[i]。但是dp[i-1]可能为负数。
以num[i-1]结尾(即dp[i-1])的最大子数组是否能加入到以nums[i]结尾的连续子数组,要看其dp[i-1]的值,如果dp[i-1]<=0,那么以nums[i]结尾的连续子数组肯定不要包含以nums[i-1]结尾的连续子数组,这样构成的以nums[i]结尾的连续子数组和才不会取得更低(实际上dp[i-1]<=0,则以nums[i]的连续子数组的最大和取的就是nums[i]),如果dp[i-1]>0 ,那么可以把 nums[i] 直接接在 dp[i - 1] 表示的那个数组的后面,得到和更大的连续子数组。

代码

暴力解法:超时

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        temp =0
        max=nums[0]
        pre = [0]
        sum = 0
        for i in range(n):
            sum+=nums[i]
            pre.append(sum)
        for i in  range(n+1):
            for j in range(0,i):
                if(pre[i]-pre[j]>max):
                    max = pre[i]-pre[j]

        return max

动态规划

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        if(n ==0):
            return 0
        dp = [0 for i in range(n)]
        dp[0]=nums[0]
        for i in range(1,n):
            if (dp[i-1]>0):
                dp[i]=dp[i-1]+nums[i]
            else:
                dp[i]=nums[i]

        return max(dp)