Maximum sum of consecutive subarrays
Enter an integer array. One or more consecutive integers in the array form a sub-array. Find the maximum value of the sum of all sub-arrays.
The required time complexity is O(n).
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The sum of consecutive sub-arrays [4,-1,2,1] is the largest, which is 6.
prompt:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
Dynamic programming analysis:
General idea: Define a dynamic programming array dp with the same size as the target array num. After traversal, the value of dp[i] is the maximum sum of continuous sub-arrays ending with element num[i]. The implementation principle is as follows
State definition:
1. Let the dynamic programming list dp, dp[i] represent the maximum sum of consecutive sub-arrays ending with element nums[i] .
Why define the maximum sum dp[i] must contain the element nums[i]: to ensure the correctness of dp[i] recursively to dp[i + 1];
If nums[i] is not included, the continuous sub-array requirement of the question will not be met during recursion.
2. Transfer equation: If dp[i-1]≤0, it means that dp[i-1] has a negative contribution to dp[i], that is, dp[i-1] + nums[i] is not as good as nums[i] itself Big.
When dp[i-1]> 0: execute dp[i] = dp[i- 1] + nums[i];
When dp[i -1]≤0: execute dp[i]= nums[i];
3. Initial state:
dp[0] = nums[0], that is, the maximum sum of consecutive sub-arrays ending in nums[0] is nums[0].
4. Return value:
Returns the maximum value in the dp list, which represents the global maximum value.
public int maxSubArray1(int[] nums){
//暴力破解2优化,O(n^2)
int n = -100;
for (int i = 1; i < nums.length; i++) {
int sum = 0;
for (int j = i; j <= nums.length; j++){
sum += nums[j];
if (sum > n){
n = sum;
}
}
}
return n;
}
public int maxSubArray2(int[] nums){
//动态规划
//创建一个同样大小的数组dp[i]表示以元素num[i]为结尾的连续子数组最大和
int[] dp = new int[nums.length];
dp[0]=nums[0];//初始化dp[0]
for(int j = 1;j<nums.length;j++){
//判断条件,dp[j-1]>0表示以元素num[i]为结尾的连续子数组最大和大于0
// 即可对之后组成更大的连续子数组有正贡献
//dp[j-1]<0,表示以元素num[i]为结尾的连续子数组最大和小于0,
// 不再参与之后的连续子数组,子数组从新积累
if(dp[j-1]>0){
dp[j] = dp[j-1]+nums[j];
}else{
dp[j] = nums[j];
}
}
int max = Integer.MIN_VALUE;
for(int i = 0;i<dp.length;i++){
//遍历dp,找到最大值
if(dp[i]>max)
max = dp[i];
}
return max;
}
public int maxSubArray3(int[] nums) {
//同样的功能大佬的代码简单到离谱,阿巴阿巴
int res = nums[0];
for(int i = 1; i < nums.length; i++) {
nums[i] += Math.max(nums[i - 1], 0);
res = Math.max(res, nums[i]);
}
return res;
}
public class MaxSubArray {
public static void main(String[] args) {
Solution solution = new Solution();
int[] arr = new int[]{
-2,1,-3,4,-1,2,1,-5,4};//结果为6,ok
System.out.println(solution.maxSubArray3(arr));
}
}
Summary: Getting started with dynamic programming. At the beginning, even the simplest brute force solution was not written independently. Now the idea of solving these problems is suddenly clear, which is too powerful.
Brute force cracking is a double loop comparing the size of each sub-array sum, starting from 0 [0], [0,1], [0,1,2], until [0,1,2,...n], and then from Start at 1, [1],[1,2],[1,2,3] all the way to [1,2,...n], and then start at 2...
sum(0,0) | ||
sum(0,1) | sum(1,1) | |
sum(0,2) | sum(1,2) | sum(2,2) |
sum(0,3) | sum(1,3) | sum(2,3) |
… | … | … |
--------------------------------------->
The dynamic programming idea of this problem is to find the largest sub-array of each array ending in num[i] and store it in the array dp, and then traverse dp to find the maximum
Max | |||
---|---|---|---|
sum(0,0) | dp[0] | ||
sum(0,1) | sum(1,1) | dp[1] | |
sum(0,2) | sum(1,2) | sum(2,2) | dp[2] |
sum(0,3) | sum(1,3) | sum(2,3) | dp[3] |
… | … | … | dp[j] |
Calculation method of maximum dp[j]
dp[j] = dp[j-1]+nums[j]; dp[j-1]>0
dp[j] = nums[j]; dp[j-1]<0
You can understand this method by calculating the examples given by yourself.