输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
class Solution {
public int maxSubArray(int[] nums) {
//动态的核心思路是可以做一个有记忆性的数组,通常三步走
//1.定义一个dp[i]数组。2.梳理出动态规划表达式。3.梳理出初值。
//我的第一种解法时间复杂度O(n2),思路就是把所有可能的情况用一个二维数组表示,行元素表示第几个数字,列元素表示几个数字求和
//这不是动态规划,这是暴力法,动态规划需要用到前面的值,有记忆性。这个做法会超出内存限制,OOM真有意思,第一次产生这个问题
if(nums.length == 0) {return 0;}
int [][] dp = new int[nums.length][nums.length];
//初始化
for(int i = 0;i < nums.length; i++){
dp[i][i] = nums[i];
}
int max = nums[0];
for(int i = 0; i < nums.length; i++){
for(int j = i + 1;j < nums.length; j++){
dp[i][j] = dp[i][j - 1] + nums[j];
max = Math.max(max, dp[i][j]);
}
max = Math.max(max, dp[i][i]);
}
return max;
//动态规划:dp[i] 表示第i个元素(包括i)之前的最大值,
int [] dp = new int [nums.length];
dp[0] = nums[0];
int res = nums[0];
for(int i = 1; i < nums.length; i++){
dp[i] = Math.max(dp[i - 1], 0);
//这里如果前面的一个值,小于0则是一个负反馈,加上前面值会比nums[i]还小。
dp[i] += nums[i];//前面i-1的和小于0,则从从这个数开始作为第一个数字
res = Math.max(res, dp[i]);//每次求和则保留前面元素和最大值进行比较,保留最大值
}
//这个解法和上面的解法比无法直到最大连续数字,但是可以直到和,且和会改变
return res;
}
}