1,问题描述
918. 环形子数组的最大和
难度:中等
给定一个长度为 n
的环形整数数组 nums
,返回 nums
的非空 子数组 的最大可能和 。
环形数组 意味着数组的末端将会与开头相连呈环状。形式上, nums[i]
的下一个元素是 nums[(i + 1) % n]
, nums[i]
的前一个元素是 nums[(i - 1 + n) % n]
。
子数组 最多只能包含固定缓冲区 nums
中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j]
,不存在 i <= k1, k2 <= j
其中 k1 % n == k2 % n
。
示例 1:
1 2 3
| 输入:nums = [1,-2,3,-2] 输出:3 解释:从子数组 [3] 得到最大和 3
|
示例 2:
1 2 3
| 输入:nums = [5,-3,5] 输出:10 解释:从子数组 [5,5] 得到最大和 5 + 5 = 10
|
示例 3:
1 2 3
| 输入:nums = [3,-2,2,-3] 输出:3 解释:从子数组 [3] 和 [3,-2,2] 都可以得到最大和 3
|
提示:
n == nums.length
1 <= n <= 3 * 10^4
-3 * 104 <= nums[i] <= 3 * 10^4
2,初步思考
相似的题目是53,只是多了一个环
有好几种解法
3,代码处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| import java.util.ArrayDeque; import java.util.Arrays; import java.util.Deque;
public class _918环形子数组的最大和 {
public int maxSubarraySumCircular_option(int[] nums) { int len = nums.length; int sum = nums[0]; int preMax = nums[0]; int resMax = nums[0]; int preMin = nums[0]; int resMin = nums[0]; for (int i = 1; i < len; i++) { sum += nums[i]; preMax = Math.max(nums[i], nums[i] + preMax); resMax = Math.max(resMax, preMax); preMin = Math.min(nums[i], nums[i] + preMin); resMin = Math.min(resMin, preMin); } return Math.max(resMax, sum - resMin == 0 ? resMax : (sum - resMin)); }
public int maxSubarraySumCircular(int[] nums) { int n = nums.length; int[] leftMax = new int[n]; leftMax[0] = nums[0]; int leftSum = nums[0]; int pre = nums[0]; int res = nums[0]; for (int i = 1; i < n; i++) { pre = Math.max(pre + nums[i], nums[i]); res = Math.max(res, pre); leftSum += nums[i]; leftMax[i] = Math.max(leftMax[i - 1], leftSum); }
int rightSum = 0; for (int i = n - 1; i > 0; i--) { rightSum += nums[i]; res = Math.max(res, rightSum + leftMax[i - 1]); } return res; }
public int maxSubarraySumCircular_prefix_sum(int[] nums) { int n = nums.length; int[] prefixSum = new int[n * 2]; prefixSum[0] = nums[0]; int sum = nums[0]; int min = nums[0]; int max = nums[0]; int res = nums[0]; for (int i = 1; i < n; i++) { sum += nums[i]; if (sum > max) { max = sum; res = Math.max(res, max - min); } else if (sum < min) { min = sum; } prefixSum[i] = sum; } for (int i = 0; i < n; i++) { sum += nums[i]; if (sum > max) { max = sum; res = Math.max(res, max - min); } else if (sum < min) { min = sum; } prefixSum[i + n] = sum; } return res; }
public int maxSubarraySumCircular_monostone_stack(int[] nums) { int n = nums.length; Deque<int[]> queue = new ArrayDeque<int[]>(); int pre = nums[0], res = nums[0]; queue.offerLast(new int[]{0, pre}); for (int i = 1; i < 2 * n; i++) { while (!queue.isEmpty() && queue.peekFirst()[0] < i - n) { queue.pollFirst(); } pre += nums[i % n]; res = Math.max(res, pre - queue.peekFirst()[1]); while (!queue.isEmpty() && queue.peekLast()[1] >= pre) { queue.pollLast(); } queue.offerLast(new int[]{i, pre}); } return res; }
public static void main(String[] args) { _918环形子数组的最大和 maxSubarraySumCircular = new _918环形子数组的最大和();
System.out.println(maxSubarraySumCircular.maxSubarraySumCircular_prefix_sum(new int[]{5, -3, 5}));
}
}
|