用 f(i) 代表以第 i 个数结尾的「连续子数组的最大和」
如何求 f(i) 呢?我们可以考虑 nums[i] 单独成为一段还是加入 f(i-1)对应的那一段,这取决于 nums[i] 和 f(i−1)+nums[i] 的大小,我们希望获得一个比较大的,于是可以写出这样的动态规划转移方程:
状态转移方程: f(i) = max(f(i-1) + nums[i], nums[i])
java实现:
class Solution {
public int maxSubArray(int[] nums) {
int n = nums.length;
if(n == 0) return 0;
//定义dp数组,dp数组中的每个值dp[i]代表着以nums[i]为结尾的最大子序和
int[] dp = new int[n];
//以nums[0]结尾的最大子序和就是nums[0]
dp[0] = nums[0];
//遍历,通过状态转移方程求得dp[i]的最大子序和
for(int i = 1; i < n; ++i){
//dp[i]的最大子序和要么是自成一派最大,要么就是当前值加上前面i - 1个数的最大子序和
//如果前边累加后还不如自己本身大,那就把前边的都扔掉,从此自己本身重新开始累加。
dp[i] = Math.max(nums[i], nums[i] + dp[i - 1]);
}
//遍历dp数组,求得dp数组中的最大值,就是该题的答案
int res = Integer.MIN_VALUE;
for(int j = 0; j < dp.length; ++j){
res = Math.max(res, dp[j]);
}
return res;
}
}
贪心思想:若当前指针所指元素之前的和小于0,则丢弃之前的数列
class Solution(object):
def maxSubArray(self, nums):
cur_sum=max_sum=nums[0]
for i in range(1,len(nums)):
cur_sum=max(nums[i],nums[i]+cur_sum)
max_sum=max(max_sum,cur_sum)
return max_sum
"""
其实这里相当于是一个比较,
比较了f(i-1)+nums[i]和nums[i]的大小,
依次遍历后nums每个数字都变成了相应的f(i),
即以第 i 个数结尾的「连续子数组的最大和」
"""
nums[i]=max(nums[i],nums[i-1]+nums[i])
return max(nums)
动态规划思想:若前一个元素大于0,则将其加到当前元素上
class Solution(object):
def maxSubArray(self, nums):
n=len(nums)
for i in range(1,n):
"""
其实这里相当于是一个比较,
比较了f(i-1)+nums[i]和nums[i]的大小,
依次遍历后nums每个数字都变成了相应的f(i),
即以第 i 个数结尾的「连续子数组的最大和」
"""
nums[i]=max(nums[i],nums[i-1]+nums[i])
return max(nums)