Table of contents
Title description:
Example:
hint:
n == nums.length
1 <= n <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
Similar topic: Maximum subarray sum
Problem-solving ideas:
Method 1: Dynamic Programming
Since the array is circular, there are two situations in the situation of the largest subarray :
-
Case 1:
The largest sub-array has only one segment, namely [i, j] { i >= 0 && j < len && i < j}
-
Case two:
There are two segments in the largest sub-array, [0, i] and [j, len - 1] { i < j}
Situation one solution:
The solution for case 1 is the same as the largest subarray and also uses dynamic programming.
-
Define the array dp = new int[len], where dp[i] represents the sum of the largest subarrays ending with subscript i .
-
Derivation of the recursive formula:
When traversing to subscript i , what should be the sum of the largest subarray ending with subscript i ?
dp[i] depends on dp[i - 1] and nums[i], where dp[i - 1] represents the sum of the largest subarrays ending with subscript i - 1 , so dp[i] = dp[i - 1 ] + nums[i], but if nums[i] is larger than dp[i - 1] + nums[i], then dp[i] = nums[i], so dp[i] = Math.max( dp[i - 1] + nums[i], nums[i]).
-
Initialize the array dp:
Through the recursive formula, we can know that dp[i] is derived from the previous one, so dp[0] must be initialized, dp[0] = nums[0].
-
Determine the traversal order:
It can be traversed from front to back.
public int maxSumOfSubArray(int[] nums){
int len = nums.length;
int[] dp = new int[len];
dp[0] = nums[0];
int ans = dp[0];
for(int i = 1; i < len; i++){
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
ans = Math.max(dp[i], ans); // 更新结果。
}
return ans;
}
Case two solution:
We need to record the maximum value of the interval [0, i], which starts from 0. For example, the maximum value of the interval [0, 2] is 10. If the sum of the interval [0, 3] is less than 10, then [0 , 3] interval is the value of [0, 2] interval.
Recording the maximum value of the interval [0, i] can be recorded in Case 1, as follows:
public int maxSumOfSubArray(int[] nums){
int len = nums.length;
int[] dp = new int[len];
dp[0] = nums[0];
int ans = dp[0];
//=========记录[0, i]区间最大值===================
int[] leftSum = new int[len];
leftSum[0] = nums[0];
int preSum = nums[0];
//==============================================
for(int i = 1; i < len; i++){
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
ans = Math.max(dp[i], ans); // 更新结果。
//========记录[0, i]区间最大值==================
preSum += nums[i]; // 记录[0, i] 区间的和。
leftSum[i] = Math.max(leftSum[i - 1], preSum);
}
return ans;
}
Next, traverse the nums array in reverse order and record the sum of [j, len - 1]. The sum of [j, len - 1] plus leftSum[j - 1] is the sum of the largest subarray in case 2 .
The complete code is as follows:
public int maxSubarraySumCircular01(int[] nums) {
int len = nums.length;
int ans = nums[0];
int[] dp = new int[len];
dp[0] = nums[0];
int[] leftSum = new int[len];
leftSum[0] = nums[0];
int preSum = nums[0];
for (int i = 1; i < len; i++) {
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
ans = Math.max(dp[i], ans);
preSum += nums[i];
leftSum[i] = Math.max(leftSum[i - 1], preSum);
}
int backSum = 0; // 记录[j, len - 1]的和
for (int j = len - 1; j > 0; j--) {
backSum += nums[j];
ans = Math.max(ans, backSum + leftSum[j - 1]);
}
return ans;
}